\n \n \n \n There is no broken links in this build!!\n \n \n \n
\n{:else}\n
\n
\n \n \n \n
\n
\n \n
\n
\n {#if foundUnscannableLinks.length > 0}\n \n hideShow()}\n cssClass=\"inline-block cursor-pointer\">\n {#if !hiddenRows}\n \n {:else}\n \n {/if}\n \n Found Unscannable Links:\n \n {#if !hiddenRows}\n \n See our Knowledge Base (KB) to learn more about \n why some working websites are reported as broken in CodeAuditor?\n \n
"
- ],
- "names": [],
- "mappings": "AA2EA,QAAQ,eAAC,CAAC,AACV,MAAM,CAAE,KAAK,AACb,CAAC;ACpED,EAAE,eAAC,CAAC,AACF,UAAU,CAAE,KAAK,CAAC,KAAK,CAAC,OAAO,AACjC,CAAC;ACKD,EAAE,8BAAC,CAAC,AACF,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAC9B,WAAW,CAAE,KAAK,CAClB,aAAa,CAAE,IAAI,AACrB,CAAC,AAED,iBAAE,CAAC,IAAI,eAAC,CAAC,AACP,UAAU,CAAE,IAAI,CAChB,YAAY,CAAE,GAAG,CACjB,aAAa,CAAE,IAAI,AACrB,CAAC;ACqBD,UAAU,eAAC,CAAC,AACV,UAAU,CAAE,IAAI,AAClB,CAAC,AAED,yBAAU,MAAM,AAAC,CAAC,AAChB,UAAU,CAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAC3C,MAAM,CAAE,OAAO,AACjB,CAAC;ACxCD,EAAE,8BAAC,CAAC,AACF,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAC9B,WAAW,CAAE,KAAK,CAClB,aAAa,CAAE,IAAI,AACrB,CAAC,AAED,iBAAE,CAAC,IAAI,eAAC,CAAC,AACP,UAAU,CAAE,IAAI,CAChB,YAAY,CAAE,GAAG,CACjB,aAAa,CAAE,IAAI,AACrB,CAAC;ACPD,EAAE,8BAAC,CAAC,AACF,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAC9B,WAAW,CAAE,KAAK,CAClB,aAAa,CAAE,IAAI,AACrB,CAAC,AAED,iBAAE,CAAC,IAAI,eAAC,CAAC,AACP,UAAU,CAAE,IAAI,CAChB,YAAY,CAAE,GAAG,CACjB,aAAa,CAAE,IAAI,AACrB,CAAC,AAED,UAAU,8BAAC,CAAC,AACV,UAAU,CAAE,IAAI,AAClB,CAAC,AAED,wCAAU,MAAM,AAAC,CAAC,AAChB,UAAU,CAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAC3C,MAAM,CAAE,OAAO,AACjB,CAAC;ACpBD,EAAE,8BAAC,CAAC,AACF,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAC9B,WAAW,CAAE,KAAK,CAClB,aAAa,CAAE,IAAI,AACrB,CAAC,AAED,iBAAE,CAAC,IAAI,eAAC,CAAC,AACP,UAAU,CAAE,IAAI,CAChB,YAAY,CAAE,GAAG,CACjB,aAAa,CAAE,IAAI,AACrB,CAAC;ACyED,OAAO,cAAC,CAAC,AACP,UAAU,CAAE,KAAK,CACjB,KAAK,CAAE,OAAO,AAChB,CAAC,AACD,qBAAO,MAAM,AAAC,CAAC,AACb,KAAK,CAAE,OAAO,AAChB,CAAC,AACD,qBAAO,QAAQ,AAAC,CAAC,AACf,KAAK,CAAE,OAAO,AAChB,CAAC,AACD,WAAW,cAAC,CAAC,AACX,MAAM,CAAE,IAAI,AACd,CAAC;ACnGD,EAAE,8BAAC,CAAC,AACF,UAAU,CAAE,IAAI,CAChB,aAAa,CAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAC9B,WAAW,CAAE,KAAK,CAClB,aAAa,CAAE,IAAI,AACrB,CAAC,AAED,iBAAE,CAAC,IAAI,eAAC,CAAC,AACP,UAAU,CAAE,IAAI,CAChB,YAAY,CAAE,GAAG,CACjB,aAAa,CAAE,IAAI,AACrB,CAAC;ACiBD,OAAO,cAAC,CAAC,AACP,UAAU,CAAE,KAAK,CACjB,KAAK,CAAE,OAAO,AAChB,CAAC,AACD,qBAAO,MAAM,AAAC,CAAC,AACb,KAAK,CAAE,OAAO,AAChB,CAAC,AACD,qBAAO,QAAQ,AAAC,CAAC,AACf,KAAK,CAAE,OAAO,AAChB,CAAC;ACpDD,QAAQ,cAAC,CAAC,AACR,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACZ,gBAAgB,CAAE,IAAI,CAEtB,aAAa,CAAE,IAAI,CACnB,iBAAiB,CAAE,yBAAW,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,CACtD,SAAS,CAAE,yBAAW,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,AAChD,CAAC,AAED,mBAAmB,yBAAY,CAAC,AAC9B,EAAE,AAAC,CAAC,AACF,iBAAiB,CAAE,MAAM,CAAC,CAAC,AAC7B,CAAC,AACD,IAAI,AAAC,CAAC,AACJ,iBAAiB,CAAE,MAAM,CAAC,CAAC,CAC3B,OAAO,CAAE,CAAC,AACZ,CAAC,AACH,CAAC,AAED,WAAW,yBAAY,CAAC,AACtB,EAAE,AAAC,CAAC,AACF,iBAAiB,CAAE,MAAM,CAAC,CAAC,CAC3B,SAAS,CAAE,MAAM,CAAC,CAAC,AACrB,CAAC,AACD,IAAI,AAAC,CAAC,AACJ,iBAAiB,CAAE,MAAM,CAAC,CAAC,CAC3B,SAAS,CAAE,MAAM,CAAC,CAAC,CACnB,OAAO,CAAE,CAAC,AACZ,CAAC,AACH,CAAC;AC9BD,QAAQ,4BAAC,CAAC,AACR,MAAM,CAAE,KAAK,CAAC,IAAI,CAClB,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACZ,UAAU,CAAE,MAAM,CAClB,SAAS,CAAE,IAAI,AACjB,CAAC,AAED,sBAAQ,CAAG,GAAG,cAAC,CAAC,AACd,gBAAgB,CAAE,IAAI,CACtB,MAAM,CAAE,IAAI,CACZ,KAAK,CAAE,GAAG,CACV,OAAO,CAAE,YAAY,CAErB,iBAAiB,CAAE,6BAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAC5D,SAAS,CAAE,6BAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,AACtD,CAAC,AAED,sBAAQ,CAAC,MAAM,cAAC,CAAC,AACf,uBAAuB,CAAE,KAAK,CAC9B,eAAe,CAAE,KAAK,AACxB,CAAC,AAED,sBAAQ,CAAC,MAAM,cAAC,CAAC,AACf,uBAAuB,CAAE,GAAG,CAC5B,eAAe,CAAE,GAAG,AACtB,CAAC,AAED,sBAAQ,CAAC,MAAM,cAAC,CAAC,AACf,uBAAuB,CAAE,KAAK,CAC9B,eAAe,CAAE,KAAK,AACxB,CAAC,AAED,sBAAQ,CAAC,MAAM,cAAC,CAAC,AACf,uBAAuB,CAAE,KAAK,CAC9B,eAAe,CAAE,KAAK,AACxB,CAAC,AAED,mBAAmB,6BAAgB,CAAC,AAClC,EAAE,CACF,GAAG,CACH,IAAI,AAAC,CAAC,AACJ,iBAAiB,CAAE,OAAO,GAAG,CAAC,AAChC,CAAC,AACD,GAAG,AAAC,CAAC,AACH,iBAAiB,CAAE,OAAO,CAAC,CAAC,AAC9B,CAAC,AACH,CAAC,AAED,WAAW,6BAAgB,CAAC,AAC1B,EAAE,CACF,GAAG,CACH,IAAI,AAAC,CAAC,AACJ,SAAS,CAAE,OAAO,GAAG,CAAC,CACtB,iBAAiB,CAAE,OAAO,GAAG,CAAC,AAChC,CAAC,AACD,GAAG,AAAC,CAAC,AACH,SAAS,CAAE,OAAO,CAAC,CAAC,CACpB,iBAAiB,CAAE,OAAO,CAAC,CAAC,AAC9B,CAAC,AACH,CAAC;ACvCD,MAAM,cAAC,CAAC,AACN,UAAU,CAAE,OAAO,CAAC,IAAI,CAAC,IAAI,AAC/B,CAAC,AACD,WAAW,cAAC,CAAC,AACX,MAAM,CAAE,IAAI,AACd,CAAC,AACD,WAAW,cAAC,CAAC,AACX,MAAM,CAAE,IAAI,AACd,CAAC;ACAD,OAAO,cAAC,CAAC,AACP,KAAK,CAAE,KAAK,AACd,CAAC;AChCuB,OAAO,8BAAC,CAAC,AAC/B,MAAM,CAAE,OAAO,CACf,KAAK,CAAE,OAAO,CACd,UAAU,CAAE,EAAE,CACd,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,CACZ,QAAQ,CAAE,QAAQ,AACpB,CAAC,AACD,qCAAO,OAAO,AAAC,CAAC,AACd,OAAO,CAAE,EAAE,CACX,KAAK,CAAE,GAAG,CACV,MAAM,CAAE,GAAG,CACX,aAAa,CAAE,GAAG,CAClB,QAAQ,CAAE,QAAQ,CAClB,OAAO,CAAE,KAAK,CACd,UAAU,CAAE,IAAI,KAAK,CAAC,CACtB,GAAG,CAAE,IAAI,CACT,IAAI,CAAE,IAAI,CACV,SAAS,CAAE,UAAU,KAAK,CAAC,CAAC,KAAK,CAAC,CAClC,SAAS,CAAE,sBAAO,CAAC,IAAI,UAAU,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,AACpF,CAAC,AACD,sBAAO,CAAC,GAAG,eAAC,CAAC,AACX,OAAO,CAAE,KAAK,CACd,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,IAAI,AACd,CAAC,AACD,sBAAO,CAAC,GAAG,CAAC,mBAAI,CAChB,sBAAO,CAAC,GAAG,CAAC,sBAAO,CACnB,sBAAO,CAAC,GAAG,CAAC,MAAM,eAAC,CAAC,AAClB,IAAI,CAAE,IAAI,CACV,MAAM,CAAE,IAAI,MAAM,CAAC,CACnB,YAAY,CAAE,IAAI,CAClB,eAAe,CAAE,KAAK,CACtB,cAAc,CAAE,KAAK,AACvB,CAAC,AACD,sBAAO,CAAC,GAAG,CAAC,OAAO,eAAC,CAAC,AACnB,gBAAgB,CAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAC/B,iBAAiB,CAAE,CAAC,CACpB,SAAS,CAAE,2BAAY,CAAC,IAAI,UAAU,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,AACzF,CAAC,AACD,sBAAO,CAAC,GAAG,CAAC,IAAI,eAAC,CAAC,AAChB,gBAAgB,CAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAC/B,iBAAiB,CAAE,CAAC,CACpB,SAAS,CAAE,uBAAQ,CAAC,EAAE,CAAC,aAAa,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,AACxE,CAAC,AACD,sBAAO,CAAC,GAAG,CAAC,MAAM,eAAC,CAAC,AAClB,gBAAgB,CAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAC/B,iBAAiB,CAAE,EAAE,CACrB,SAAS,CAAE,yBAAU,CAAC,IAAI,UAAU,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,AACvF,CAAC,AACD,OAAO,SAAS,8BAAC,CAAC,AAChB,KAAK,CAAE,IAAI,AACb,CAAC,AACD,OAAO,uCAAS,OAAO,AAAC,CAAC,AACvB,IAAI,CAAE,IAAI,CACV,SAAS,CAAE,UAAU,KAAK,CAAC,CAAC,KAAK,CAAC,CAClC,SAAS,CAAE,0BAAW,CAAC,IAAI,UAAU,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,AACxF,CAAC,AAED,WAAW,2BAAa,CAAC,AACvB,GAAG,AAAC,CAAC,AACH,iBAAiB,CAAE,EAAE,AACvB,CAAC,AACD,GAAG,AAAC,CAAC,AACH,iBAAiB,CAAE,GAAG,AACxB,CAAC,AACD,IAAI,AAAC,CAAC,AACJ,iBAAiB,CAAE,GAAG,AACxB,CAAC,AACH,CAAC,AACD,WAAW,0BAAY,CAAC,AACtB,GAAG,AAAC,CAAC,AACH,SAAS,CAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,AAC5B,CAAC,AACD,GAAG,AAAC,CAAC,AACH,SAAS,CAAE,UAAU,IAAI,CAAC,CAAC,KAAK,CAAC,AACnC,CAAC,AACD,IAAI,AAAC,CAAC,AACJ,SAAS,CAAE,UAAU,KAAK,CAAC,CAAC,KAAK,CAAC,AACpC,CAAC,AACH,CAAC,AACD,WAAW,uBAAS,CAAC,AACnB,GAAG,AAAC,CAAC,AACH,iBAAiB,CAAE,EAAE,AACvB,CAAC,AACD,GAAG,AAAC,CAAC,AACH,iBAAiB,CAAE,GAAG,AACxB,CAAC,AACD,GAAG,AAAC,CAAC,AACH,iBAAiB,CAAE,GAAG,AACxB,CAAC,AACD,IAAI,AAAC,CAAC,AACJ,iBAAiB,CAAE,GAAG,AACxB,CAAC,AACH,CAAC,AACD,WAAW,sBAAQ,CAAC,AAClB,GAAG,AAAC,CAAC,AACH,SAAS,CAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,AAC5B,CAAC,AACD,GAAG,AAAC,CAAC,AACH,SAAS,CAAE,UAAU,IAAI,CAAC,CAAC,KAAK,CAAC,AACnC,CAAC,AACD,GAAG,AAAC,CAAC,AACH,SAAS,CAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,AAChC,CAAC,AACD,IAAI,AAAC,CAAC,AACJ,SAAS,CAAE,UAAU,KAAK,CAAC,CAAC,KAAK,CAAC,AACpC,CAAC,AACH,CAAC,AACD,WAAW,yBAAW,CAAC,AACrB,GAAG,AAAC,CAAC,AACH,iBAAiB,CAAE,GAAG,AACxB,CAAC,AACD,GAAG,AAAC,CAAC,AACH,iBAAiB,CAAE,GAAG,AACxB,CAAC,AACD,GAAG,AAAC,CAAC,AACH,iBAAiB,CAAE,GAAG,AACxB,CAAC,AACD,IAAI,AAAC,CAAC,AACJ,iBAAiB,CAAE,GAAG,AACxB,CAAC,AACH,CAAC,AACD,OAAO,8BAAC,CAAC,AACP,OAAO,CAAE,YAAY,CACrB,MAAM,CAAE,CAAC,CAAC,IAAI,AAChB,CAAC,AAMD,8BAAE,CAAC,AACD,UAAU,CAAE,UAAU,AACxB,CAAC,AACD,8BAAC,OAAO,CAAE,8BAAC,MAAM,AAAC,CAAC,AACjB,UAAU,CAAE,UAAU,AACxB,CAAC,AAED,UAAU,8BAAC,CAAC,AACV,OAAO,CAAE,IAAI,CACb,eAAe,CAAE,MAAM,CACvB,WAAW,CAAE,MAAM,AACrB,CAAC;AC1HD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,eAAC,CAAC,AACnB,kBAAkB,CAAE,IAAI,CACxB,MAAM,CAAE,IAAI,CAAC,CAAC,CACd,KAAK,CAAE,IAAI,AACb,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,MAAM,AAAC,CAAC,AACzB,OAAO,CAAE,IAAI,AACf,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,+BAA+B,AAAC,CAAC,AAClD,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,KAAK,CACb,MAAM,CAAE,OAAO,CACf,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CACpD,UAAU,CAAE,OAAO,CACnB,aAAa,CAAE,KAAK,CACpB,MAAM,CAAE,KAAK,CAAC,KAAK,CAAC,OAAO,AAC7B,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,sBAAsB,AAAC,CAAC,AACzC,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CACpD,MAAM,CAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CACzB,MAAM,CAAE,IAAI,CACZ,KAAK,CAAE,IAAI,CACX,aAAa,CAAE,GAAG,CAClB,UAAU,CAAE,OAAO,CACnB,MAAM,CAAE,OAAO,CACf,kBAAkB,CAAE,IAAI,CACxB,UAAU,CAAE,KAAK,AACnB,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,MAAM,+BAA+B,AAAC,CAAC,AACxD,UAAU,CAAE,OAAO,AACrB,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,kBAAkB,AAAC,CAAC,AACrC,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,KAAK,CACb,MAAM,CAAE,OAAO,CACf,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CACpD,UAAU,CAAE,OAAO,CACnB,aAAa,CAAE,KAAK,CACpB,MAAM,CAAE,KAAK,CAAC,KAAK,CAAC,OAAO,AAC7B,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,kBAAkB,AAAC,CAAC,AACrC,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CACpD,MAAM,CAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CACzB,MAAM,CAAE,IAAI,CACZ,KAAK,CAAE,IAAI,CACX,aAAa,CAAE,GAAG,CAClB,UAAU,CAAE,OAAO,CACnB,MAAM,CAAE,OAAO,AACjB,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,WAAW,AAAC,CAAC,AAC9B,KAAK,CAAE,IAAI,CACX,MAAM,CAAE,KAAK,CACb,MAAM,CAAE,OAAO,CACf,UAAU,CAAE,WAAW,CACvB,YAAY,CAAE,WAAW,CACzB,YAAY,CAAE,IAAI,CAAC,CAAC,CACpB,KAAK,CAAE,WAAW,AACpB,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,gBAAgB,AAAC,CAAC,AACnC,UAAU,CAAE,OAAO,CACnB,MAAM,CAAE,KAAK,CAAC,KAAK,CAAC,OAAO,CAC3B,aAAa,CAAE,KAAK,CACpB,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,AACtD,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,gBAAgB,AAAC,CAAC,AACnC,UAAU,CAAE,OAAO,CACnB,MAAM,CAAE,KAAK,CAAC,KAAK,CAAC,OAAO,CAC3B,aAAa,CAAE,KAAK,CACpB,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,AACtD,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,WAAW,AAAC,CAAC,AAC9B,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CACpD,MAAM,CAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CACzB,MAAM,CAAE,IAAI,CACZ,KAAK,CAAE,IAAI,CACX,aAAa,CAAE,GAAG,CAClB,UAAU,CAAE,OAAO,CACnB,MAAM,CAAE,OAAO,AACjB,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,MAAM,gBAAgB,AAAC,CAAC,AACzC,UAAU,CAAE,OAAO,AACrB,CAAC,AACD,KAAK,CAAC,IAAI,CAAC,OAAO,gBAAC,MAAM,gBAAgB,AAAC,CAAC,AACzC,UAAU,CAAE,OAAO,AACrB,CAAC;AC/FD,GAAG,cAAC,CAAC,AACJ,MAAM,CAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CACtB,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAC5B,UAAU,CAAE,KAAK,CACjB,aAAa,CAAE,GAAG,CAClB,OAAO,CAAE,GAAG,CACZ,QAAQ,CAAE,QAAQ,AACnB,CAAC;ACsCD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAG,oBAAK,CAAC,IAAI,eAAC,CAAC,AAChC,UAAU,CAAE,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,AAC7C,CAAC,AAED,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAG,oBAAK,CAAC,mBAAI,MAAM,CACtC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAG,oBAAK,MAAM,CAAC,IAAI,eAAC,CAAC,AACtC,SAAS,CAAE,MAAM,GAAG,CAAC,AACvB,CAAC,AAED,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAG,oBAAK,CAAC,IAAI,eAAC,CAAC,AACxC,gBAAgB,CAAE,KAAK,CACvB,UAAU,CAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,AACzC,CAAC,AAED,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAG,KAAK,8BAAC,CAAC,AACnC,KAAK,CAAE,OAAO,AAChB,CAAC;AC0GC,mBAAI,CACJ,MAAM,eAAC,CAAC,AACN,gBAAgB,CAAE,IAAI,AACxB,CAAC,AACD,GAAG,eAAC,CAAC,AACH,SAAS,CAAE,IAAI,CACf,MAAM,CAAE,IAAI,AACd,CAAC,AACD,IAAI,eAAC,CAAC,AACN,OAAO,CAAE,IAAI,CACb,UAAU,CAAE,KAAK,CACjB,cAAc,CAAE,MAAM,CACtB,OAAO,CAAE,CAAC,AACZ,CAAC,AACC,IAAI,eAAC,CAAC,AACN,IAAI,CAAE,CAAC,AACT,CAAC;AC7LD,mBAAK,CAAE,KAAK,cAAC,CAAC,AACZ,KAAK,CAAE,KAAK;AACd,CAAC"
-}
\ No newline at end of file
diff --git a/ui/public/build/bundle.js b/ui/public/build/bundle.js
deleted file mode 100644
index 2310ff0f..00000000
--- a/ui/public/build/bundle.js
+++ /dev/null
@@ -1,85884 +0,0 @@
-
-(function(l, r) { if (l.getElementById('livereloadscript')) return; r = l.createElement('script'); r.async = 1; r.src = '//' + (window.location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1'; r.id = 'livereloadscript'; l.getElementsByTagName('head')[0].appendChild(r) })(window.document);
-var app = (function () {
- 'use strict';
-
- function noop$1() { }
- const identity$2 = x => x;
- function assign$1(tar, src) {
- // @ts-ignore
- for (const k in src)
- tar[k] = src[k];
- return tar;
- }
- // Adapted from https://github.com/then/is-promise/blob/master/index.js
- // Distributed under MIT License https://github.com/then/is-promise/blob/master/LICENSE
- function is_promise(value) {
- return !!value && (typeof value === 'object' || typeof value === 'function') && typeof value.then === 'function';
- }
- function add_location(element, file, line, column, char) {
- element.__svelte_meta = {
- loc: { file, line, column, char }
- };
- }
- function run(fn) {
- return fn();
- }
- function blank_object() {
- return Object.create(null);
- }
- function run_all(fns) {
- fns.forEach(run);
- }
- function is_function(thing) {
- return typeof thing === 'function';
- }
- function safe_not_equal(a, b) {
- return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
- }
- let src_url_equal_anchor;
- function src_url_equal(element_src, url) {
- if (!src_url_equal_anchor) {
- src_url_equal_anchor = document.createElement('a');
- }
- src_url_equal_anchor.href = url;
- return element_src === src_url_equal_anchor.href;
- }
- function is_empty(obj) {
- return Object.keys(obj).length === 0;
- }
- function validate_store(store, name) {
- if (store != null && typeof store.subscribe !== 'function') {
- throw new Error(`'${name}' is not a store with a 'subscribe' method`);
- }
- }
- function subscribe(store, ...callbacks) {
- if (store == null) {
- return noop$1;
- }
- const unsub = store.subscribe(...callbacks);
- return unsub.unsubscribe ? () => unsub.unsubscribe() : unsub;
- }
- function get_store_value(store) {
- let value;
- subscribe(store, _ => value = _)();
- return value;
- }
- function component_subscribe(component, store, callback) {
- component.$$.on_destroy.push(subscribe(store, callback));
- }
- function create_slot(definition, ctx, $$scope, fn) {
- if (definition) {
- const slot_ctx = get_slot_context(definition, ctx, $$scope, fn);
- return definition[0](slot_ctx);
- }
- }
- function get_slot_context(definition, ctx, $$scope, fn) {
- return definition[1] && fn
- ? assign$1($$scope.ctx.slice(), definition[1](fn(ctx)))
- : $$scope.ctx;
- }
- function get_slot_changes(definition, $$scope, dirty, fn) {
- if (definition[2] && fn) {
- const lets = definition[2](fn(dirty));
- if ($$scope.dirty === undefined) {
- return lets;
- }
- if (typeof lets === 'object') {
- const merged = [];
- const len = Math.max($$scope.dirty.length, lets.length);
- for (let i = 0; i < len; i += 1) {
- merged[i] = $$scope.dirty[i] | lets[i];
- }
- return merged;
- }
- return $$scope.dirty | lets;
- }
- return $$scope.dirty;
- }
- function update_slot_base(slot, slot_definition, ctx, $$scope, slot_changes, get_slot_context_fn) {
- if (slot_changes) {
- const slot_context = get_slot_context(slot_definition, ctx, $$scope, get_slot_context_fn);
- slot.p(slot_context, slot_changes);
- }
- }
- function get_all_dirty_from_scope($$scope) {
- if ($$scope.ctx.length > 32) {
- const dirty = [];
- const length = $$scope.ctx.length / 32;
- for (let i = 0; i < length; i++) {
- dirty[i] = -1;
- }
- return dirty;
- }
- return -1;
- }
- function null_to_empty(value) {
- return value == null ? '' : value;
- }
- function action_destroyer(action_result) {
- return action_result && is_function(action_result.destroy) ? action_result.destroy : noop$1;
- }
- function split_css_unit(value) {
- const split = typeof value === 'string' && value.match(/^\s*(-?[\d.]+)([^\s]*)\s*$/);
- return split ? [parseFloat(split[1]), split[2] || 'px'] : [value, 'px'];
- }
-
- const is_client = typeof window !== 'undefined';
- let now = is_client
- ? () => window.performance.now()
- : () => Date.now();
- let raf = is_client ? cb => requestAnimationFrame(cb) : noop$1;
-
- const tasks = new Set();
- function run_tasks(now) {
- tasks.forEach(task => {
- if (!task.c(now)) {
- tasks.delete(task);
- task.f();
- }
- });
- if (tasks.size !== 0)
- raf(run_tasks);
- }
- /**
- * Creates a new task that runs on each raf frame
- * until it returns a falsy value or is aborted
- */
- function loop(callback) {
- let task;
- if (tasks.size === 0)
- raf(run_tasks);
- return {
- promise: new Promise(fulfill => {
- tasks.add(task = { c: callback, f: fulfill });
- }),
- abort() {
- tasks.delete(task);
- }
- };
- }
-
- const globals = (typeof window !== 'undefined'
- ? window
- : typeof globalThis !== 'undefined'
- ? globalThis
- : global);
- function append(target, node) {
- target.appendChild(node);
- }
- function get_root_for_style(node) {
- if (!node)
- return document;
- const root = node.getRootNode ? node.getRootNode() : node.ownerDocument;
- if (root && root.host) {
- return root;
- }
- return node.ownerDocument;
- }
- function append_empty_stylesheet(node) {
- const style_element = element('style');
- append_stylesheet(get_root_for_style(node), style_element);
- return style_element.sheet;
- }
- function append_stylesheet(node, style) {
- append(node.head || node, style);
- return style.sheet;
- }
- function insert(target, node, anchor) {
- target.insertBefore(node, anchor || null);
- }
- function detach(node) {
- if (node.parentNode) {
- node.parentNode.removeChild(node);
- }
- }
- function destroy_each(iterations, detaching) {
- for (let i = 0; i < iterations.length; i += 1) {
- if (iterations[i])
- iterations[i].d(detaching);
- }
- }
- function element(name) {
- return document.createElement(name);
- }
- function svg_element(name) {
- return document.createElementNS('http://www.w3.org/2000/svg', name);
- }
- function text(data) {
- return document.createTextNode(data);
- }
- function space() {
- return text(' ');
- }
- function empty() {
- return text('');
- }
- function listen(node, event, handler, options) {
- node.addEventListener(event, handler, options);
- return () => node.removeEventListener(event, handler, options);
- }
- function prevent_default(fn) {
- return function (event) {
- event.preventDefault();
- // @ts-ignore
- return fn.call(this, event);
- };
- }
- function attr(node, attribute, value) {
- if (value == null)
- node.removeAttribute(attribute);
- else if (node.getAttribute(attribute) !== value)
- node.setAttribute(attribute, value);
- }
- function get_binding_group_value(group, __value, checked) {
- const value = new Set();
- for (let i = 0; i < group.length; i += 1) {
- if (group[i].checked)
- value.add(group[i].__value);
- }
- if (!checked) {
- value.delete(__value);
- }
- return Array.from(value);
- }
- function init_binding_group(group) {
- let _inputs;
- return {
- /* push */ p(...inputs) {
- _inputs = inputs;
- _inputs.forEach(input => group.push(input));
- },
- /* remove */ r() {
- _inputs.forEach(input => group.splice(group.indexOf(input), 1));
- }
- };
- }
- function to_number(value) {
- return value === '' ? null : +value;
- }
- function children(element) {
- return Array.from(element.childNodes);
- }
- function set_input_value(input, value) {
- input.value = value == null ? '' : value;
- }
- function set_style(node, key, value, important) {
- if (value == null) {
- node.style.removeProperty(key);
- }
- else {
- node.style.setProperty(key, value, important ? 'important' : '');
- }
- }
- function select_option(select, value, mounting) {
- for (let i = 0; i < select.options.length; i += 1) {
- const option = select.options[i];
- if (option.__value === value) {
- option.selected = true;
- return;
- }
- }
- if (!mounting || value !== undefined) {
- select.selectedIndex = -1; // no option should be selected
- }
- }
- function select_value(select) {
- const selected_option = select.querySelector(':checked');
- return selected_option && selected_option.__value;
- }
- function toggle_class(element, name, toggle) {
- element.classList[toggle ? 'add' : 'remove'](name);
- }
- function custom_event(type, detail, { bubbles = false, cancelable = false } = {}) {
- const e = document.createEvent('CustomEvent');
- e.initCustomEvent(type, bubbles, cancelable, detail);
- return e;
- }
-
- // we need to store the information for multiple documents because a Svelte application could also contain iframes
- // https://github.com/sveltejs/svelte/issues/3624
- const managed_styles = new Map();
- let active = 0;
- // https://github.com/darkskyapp/string-hash/blob/master/index.js
- function hash(str) {
- let hash = 5381;
- let i = str.length;
- while (i--)
- hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
- return hash >>> 0;
- }
- function create_style_information(doc, node) {
- const info = { stylesheet: append_empty_stylesheet(node), rules: {} };
- managed_styles.set(doc, info);
- return info;
- }
- function create_rule(node, a, b, duration, delay, ease, fn, uid = 0) {
- const step = 16.666 / duration;
- let keyframes = '{\n';
- for (let p = 0; p <= 1; p += step) {
- const t = a + (b - a) * ease(p);
- keyframes += p * 100 + `%{${fn(t, 1 - t)}}\n`;
- }
- const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`;
- const name = `__svelte_${hash(rule)}_${uid}`;
- const doc = get_root_for_style(node);
- const { stylesheet, rules } = managed_styles.get(doc) || create_style_information(doc, node);
- if (!rules[name]) {
- rules[name] = true;
- stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length);
- }
- const animation = node.style.animation || '';
- node.style.animation = `${animation ? `${animation}, ` : ''}${name} ${duration}ms linear ${delay}ms 1 both`;
- active += 1;
- return name;
- }
- function delete_rule(node, name) {
- const previous = (node.style.animation || '').split(', ');
- const next = previous.filter(name
- ? anim => anim.indexOf(name) < 0 // remove specific animation
- : anim => anim.indexOf('__svelte') === -1 // remove all Svelte animations
- );
- const deleted = previous.length - next.length;
- if (deleted) {
- node.style.animation = next.join(', ');
- active -= deleted;
- if (!active)
- clear_rules();
- }
- }
- function clear_rules() {
- raf(() => {
- if (active)
- return;
- managed_styles.forEach(info => {
- const { ownerNode } = info.stylesheet;
- // there is no ownerNode if it runs on jsdom.
- if (ownerNode)
- detach(ownerNode);
- });
- managed_styles.clear();
- });
- }
-
- let current_component;
- function set_current_component(component) {
- current_component = component;
- }
- function get_current_component() {
- if (!current_component)
- throw new Error('Function called outside component initialization');
- return current_component;
- }
- /**
- * The `onMount` function schedules a callback to run as soon as the component has been mounted to the DOM.
- * It must be called during the component's initialisation (but doesn't need to live *inside* the component;
- * it can be called from an external module).
- *
- * `onMount` does not run inside a [server-side component](/docs#run-time-server-side-component-api).
- *
- * https://svelte.dev/docs#run-time-svelte-onmount
- */
- function onMount(fn) {
- get_current_component().$$.on_mount.push(fn);
- }
- /**
- * Schedules a callback to run immediately before the component is unmounted.
- *
- * Out of `onMount`, `beforeUpdate`, `afterUpdate` and `onDestroy`, this is the
- * only one that runs inside a server-side component.
- *
- * https://svelte.dev/docs#run-time-svelte-ondestroy
- */
- function onDestroy(fn) {
- get_current_component().$$.on_destroy.push(fn);
- }
- /**
- * Creates an event dispatcher that can be used to dispatch [component events](/docs#template-syntax-component-directives-on-eventname).
- * Event dispatchers are functions that can take two arguments: `name` and `detail`.
- *
- * Component events created with `createEventDispatcher` create a
- * [CustomEvent](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent).
- * These events do not [bubble](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture).
- * The `detail` argument corresponds to the [CustomEvent.detail](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/detail)
- * property and can contain any type of data.
- *
- * https://svelte.dev/docs#run-time-svelte-createeventdispatcher
- */
- function createEventDispatcher() {
- const component = get_current_component();
- return (type, detail, { cancelable = false } = {}) => {
- const callbacks = component.$$.callbacks[type];
- if (callbacks) {
- // TODO are there situations where events could be dispatched
- // in a server (non-DOM) environment?
- const event = custom_event(type, detail, { cancelable });
- callbacks.slice().forEach(fn => {
- fn.call(component, event);
- });
- return !event.defaultPrevented;
- }
- return true;
- };
- }
- // TODO figure out if we still want to support
- // shorthand events, or if we want to implement
- // a real bubbling mechanism
- function bubble(component, event) {
- const callbacks = component.$$.callbacks[event.type];
- if (callbacks) {
- // @ts-ignore
- callbacks.slice().forEach(fn => fn.call(this, event));
- }
- }
-
- const dirty_components = [];
- const binding_callbacks = [];
- let render_callbacks = [];
- const flush_callbacks = [];
- const resolved_promise = /* @__PURE__ */ Promise.resolve();
- let update_scheduled = false;
- function schedule_update() {
- if (!update_scheduled) {
- update_scheduled = true;
- resolved_promise.then(flush);
- }
- }
- function add_render_callback(fn) {
- render_callbacks.push(fn);
- }
- function add_flush_callback(fn) {
- flush_callbacks.push(fn);
- }
- // flush() calls callbacks in this order:
- // 1. All beforeUpdate callbacks, in order: parents before children
- // 2. All bind:this callbacks, in reverse order: children before parents.
- // 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
- // for afterUpdates called during the initial onMount, which are called in
- // reverse order: children before parents.
- // Since callbacks might update component values, which could trigger another
- // call to flush(), the following steps guard against this:
- // 1. During beforeUpdate, any updated components will be added to the
- // dirty_components array and will cause a reentrant call to flush(). Because
- // the flush index is kept outside the function, the reentrant call will pick
- // up where the earlier call left off and go through all dirty components. The
- // current_component value is saved and restored so that the reentrant call will
- // not interfere with the "parent" flush() call.
- // 2. bind:this callbacks cannot trigger new flush() calls.
- // 3. During afterUpdate, any updated components will NOT have their afterUpdate
- // callback called a second time; the seen_callbacks set, outside the flush()
- // function, guarantees this behavior.
- const seen_callbacks = new Set();
- let flushidx = 0; // Do *not* move this inside the flush() function
- function flush() {
- // Do not reenter flush while dirty components are updated, as this can
- // result in an infinite loop. Instead, let the inner flush handle it.
- // Reentrancy is ok afterwards for bindings etc.
- if (flushidx !== 0) {
- return;
- }
- const saved_component = current_component;
- do {
- // first, call beforeUpdate functions
- // and update components
- try {
- while (flushidx < dirty_components.length) {
- const component = dirty_components[flushidx];
- flushidx++;
- set_current_component(component);
- update$1(component.$$);
- }
- }
- catch (e) {
- // reset dirty state to not end up in a deadlocked state and then rethrow
- dirty_components.length = 0;
- flushidx = 0;
- throw e;
- }
- set_current_component(null);
- dirty_components.length = 0;
- flushidx = 0;
- while (binding_callbacks.length)
- binding_callbacks.pop()();
- // then, once components are updated, call
- // afterUpdate functions. This may cause
- // subsequent updates...
- for (let i = 0; i < render_callbacks.length; i += 1) {
- const callback = render_callbacks[i];
- if (!seen_callbacks.has(callback)) {
- // ...so guard against infinite loops
- seen_callbacks.add(callback);
- callback();
- }
- }
- render_callbacks.length = 0;
- } while (dirty_components.length);
- while (flush_callbacks.length) {
- flush_callbacks.pop()();
- }
- update_scheduled = false;
- seen_callbacks.clear();
- set_current_component(saved_component);
- }
- function update$1($$) {
- if ($$.fragment !== null) {
- $$.update();
- run_all($$.before_update);
- const dirty = $$.dirty;
- $$.dirty = [-1];
- $$.fragment && $$.fragment.p($$.ctx, dirty);
- $$.after_update.forEach(add_render_callback);
- }
- }
- /**
- * Useful for example to execute remaining `afterUpdate` callbacks before executing `destroy`.
- */
- function flush_render_callbacks(fns) {
- const filtered = [];
- const targets = [];
- render_callbacks.forEach((c) => fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c));
- targets.forEach((c) => c());
- render_callbacks = filtered;
- }
-
- let promise;
- function wait() {
- if (!promise) {
- promise = Promise.resolve();
- promise.then(() => {
- promise = null;
- });
- }
- return promise;
- }
- function dispatch(node, direction, kind) {
- node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}${kind}`));
- }
- const outroing = new Set();
- let outros;
- function group_outros() {
- outros = {
- r: 0,
- c: [],
- p: outros // parent group
- };
- }
- function check_outros() {
- if (!outros.r) {
- run_all(outros.c);
- }
- outros = outros.p;
- }
- function transition_in(block, local) {
- if (block && block.i) {
- outroing.delete(block);
- block.i(local);
- }
- }
- function transition_out(block, local, detach, callback) {
- if (block && block.o) {
- if (outroing.has(block))
- return;
- outroing.add(block);
- outros.c.push(() => {
- outroing.delete(block);
- if (callback) {
- if (detach)
- block.d(1);
- callback();
- }
- });
- block.o(local);
- }
- else if (callback) {
- callback();
- }
- }
- const null_transition = { duration: 0 };
- function create_in_transition(node, fn, params) {
- const options = { direction: 'in' };
- let config = fn(node, params, options);
- let running = false;
- let animation_name;
- let task;
- let uid = 0;
- function cleanup() {
- if (animation_name)
- delete_rule(node, animation_name);
- }
- function go() {
- const { delay = 0, duration = 300, easing = identity$2, tick = noop$1, css } = config || null_transition;
- if (css)
- animation_name = create_rule(node, 0, 1, duration, delay, easing, css, uid++);
- tick(0, 1);
- const start_time = now() + delay;
- const end_time = start_time + duration;
- if (task)
- task.abort();
- running = true;
- add_render_callback(() => dispatch(node, true, 'start'));
- task = loop(now => {
- if (running) {
- if (now >= end_time) {
- tick(1, 0);
- dispatch(node, true, 'end');
- cleanup();
- return running = false;
- }
- if (now >= start_time) {
- const t = easing((now - start_time) / duration);
- tick(t, 1 - t);
- }
- }
- return running;
- });
- }
- let started = false;
- return {
- start() {
- if (started)
- return;
- started = true;
- delete_rule(node);
- if (is_function(config)) {
- config = config(options);
- wait().then(go);
- }
- else {
- go();
- }
- },
- invalidate() {
- started = false;
- },
- end() {
- if (running) {
- cleanup();
- running = false;
- }
- }
- };
- }
- function create_out_transition(node, fn, params) {
- const options = { direction: 'out' };
- let config = fn(node, params, options);
- let running = true;
- let animation_name;
- const group = outros;
- group.r += 1;
- function go() {
- const { delay = 0, duration = 300, easing = identity$2, tick = noop$1, css } = config || null_transition;
- if (css)
- animation_name = create_rule(node, 1, 0, duration, delay, easing, css);
- const start_time = now() + delay;
- const end_time = start_time + duration;
- add_render_callback(() => dispatch(node, false, 'start'));
- loop(now => {
- if (running) {
- if (now >= end_time) {
- tick(0, 1);
- dispatch(node, false, 'end');
- if (!--group.r) {
- // this will result in `end()` being called,
- // so we don't need to clean up here
- run_all(group.c);
- }
- return false;
- }
- if (now >= start_time) {
- const t = easing((now - start_time) / duration);
- tick(1 - t, t);
- }
- }
- return running;
- });
- }
- if (is_function(config)) {
- wait().then(() => {
- // @ts-ignore
- config = config(options);
- go();
- });
- }
- else {
- go();
- }
- return {
- end(reset) {
- if (reset && config.tick) {
- config.tick(1, 0);
- }
- if (running) {
- if (animation_name)
- delete_rule(node, animation_name);
- running = false;
- }
- }
- };
- }
-
- function handle_promise(promise, info) {
- const token = info.token = {};
- function update(type, index, key, value) {
- if (info.token !== token)
- return;
- info.resolved = value;
- let child_ctx = info.ctx;
- if (key !== undefined) {
- child_ctx = child_ctx.slice();
- child_ctx[key] = value;
- }
- const block = type && (info.current = type)(child_ctx);
- let needs_flush = false;
- if (info.block) {
- if (info.blocks) {
- info.blocks.forEach((block, i) => {
- if (i !== index && block) {
- group_outros();
- transition_out(block, 1, 1, () => {
- if (info.blocks[i] === block) {
- info.blocks[i] = null;
- }
- });
- check_outros();
- }
- });
- }
- else {
- info.block.d(1);
- }
- block.c();
- transition_in(block, 1);
- block.m(info.mount(), info.anchor);
- needs_flush = true;
- }
- info.block = block;
- if (info.blocks)
- info.blocks[index] = block;
- if (needs_flush) {
- flush();
- }
- }
- if (is_promise(promise)) {
- const current_component = get_current_component();
- promise.then(value => {
- set_current_component(current_component);
- update(info.then, 1, info.value, value);
- set_current_component(null);
- }, error => {
- set_current_component(current_component);
- update(info.catch, 2, info.error, error);
- set_current_component(null);
- if (!info.hasCatch) {
- throw error;
- }
- });
- // if we previously had a then/catch block, destroy it
- if (info.current !== info.pending) {
- update(info.pending, 0);
- return true;
- }
- }
- else {
- if (info.current !== info.then) {
- update(info.then, 1, info.value, promise);
- return true;
- }
- info.resolved = promise;
- }
- }
- function update_await_block_branch(info, ctx, dirty) {
- const child_ctx = ctx.slice();
- const { resolved } = info;
- if (info.current === info.then) {
- child_ctx[info.value] = resolved;
- }
- if (info.current === info.catch) {
- child_ctx[info.error] = resolved;
- }
- info.block.p(child_ctx, dirty);
- }
-
- function bind$2(component, name, callback) {
- const index = component.$$.props[name];
- if (index !== undefined) {
- component.$$.bound[index] = callback;
- callback(component.$$.ctx[index]);
- }
- }
- function create_component(block) {
- block && block.c();
- }
- function mount_component(component, target, anchor, customElement) {
- const { fragment, after_update } = component.$$;
- fragment && fragment.m(target, anchor);
- if (!customElement) {
- // onMount happens before the initial afterUpdate
- add_render_callback(() => {
- const new_on_destroy = component.$$.on_mount.map(run).filter(is_function);
- // if the component was destroyed immediately
- // it will update the `$$.on_destroy` reference to `null`.
- // the destructured on_destroy may still reference to the old array
- if (component.$$.on_destroy) {
- component.$$.on_destroy.push(...new_on_destroy);
- }
- else {
- // Edge case - component was destroyed immediately,
- // most likely as a result of a binding initialising
- run_all(new_on_destroy);
- }
- component.$$.on_mount = [];
- });
- }
- after_update.forEach(add_render_callback);
- }
- function destroy_component(component, detaching) {
- const $$ = component.$$;
- if ($$.fragment !== null) {
- flush_render_callbacks($$.after_update);
- run_all($$.on_destroy);
- $$.fragment && $$.fragment.d(detaching);
- // TODO null out other refs, including component.$$ (but need to
- // preserve final state?)
- $$.on_destroy = $$.fragment = null;
- $$.ctx = [];
- }
- }
- function make_dirty(component, i) {
- if (component.$$.dirty[0] === -1) {
- dirty_components.push(component);
- schedule_update();
- component.$$.dirty.fill(0);
- }
- component.$$.dirty[(i / 31) | 0] |= (1 << (i % 31));
- }
- function init(component, options, instance, create_fragment, not_equal, props, append_styles, dirty = [-1]) {
- const parent_component = current_component;
- set_current_component(component);
- const $$ = component.$$ = {
- fragment: null,
- ctx: [],
- // state
- props,
- update: noop$1,
- not_equal,
- bound: blank_object(),
- // lifecycle
- on_mount: [],
- on_destroy: [],
- on_disconnect: [],
- before_update: [],
- after_update: [],
- context: new Map(options.context || (parent_component ? parent_component.$$.context : [])),
- // everything else
- callbacks: blank_object(),
- dirty,
- skip_bound: false,
- root: options.target || parent_component.$$.root
- };
- append_styles && append_styles($$.root);
- let ready = false;
- $$.ctx = instance
- ? instance(component, options.props || {}, (i, ret, ...rest) => {
- const value = rest.length ? rest[0] : ret;
- if ($$.ctx && not_equal($$.ctx[i], $$.ctx[i] = value)) {
- if (!$$.skip_bound && $$.bound[i])
- $$.bound[i](value);
- if (ready)
- make_dirty(component, i);
- }
- return ret;
- })
- : [];
- $$.update();
- ready = true;
- run_all($$.before_update);
- // `false` as a special case of no DOM component
- $$.fragment = create_fragment ? create_fragment($$.ctx) : false;
- if (options.target) {
- if (options.hydrate) {
- const nodes = children(options.target);
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- $$.fragment && $$.fragment.l(nodes);
- nodes.forEach(detach);
- }
- else {
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- $$.fragment && $$.fragment.c();
- }
- if (options.intro)
- transition_in(component.$$.fragment);
- mount_component(component, options.target, options.anchor, options.customElement);
- flush();
- }
- set_current_component(parent_component);
- }
- /**
- * Base class for Svelte components. Used when dev=false.
- */
- class SvelteComponent {
- $destroy() {
- destroy_component(this, 1);
- this.$destroy = noop$1;
- }
- $on(type, callback) {
- if (!is_function(callback)) {
- return noop$1;
- }
- const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
- callbacks.push(callback);
- return () => {
- const index = callbacks.indexOf(callback);
- if (index !== -1)
- callbacks.splice(index, 1);
- };
- }
- $set($$props) {
- if (this.$$set && !is_empty($$props)) {
- this.$$.skip_bound = true;
- this.$$set($$props);
- this.$$.skip_bound = false;
- }
- }
- }
-
- function dispatch_dev(type, detail) {
- document.dispatchEvent(custom_event(type, Object.assign({ version: '3.59.1' }, detail), { bubbles: true }));
- }
- function append_dev(target, node) {
- dispatch_dev('SvelteDOMInsert', { target, node });
- append(target, node);
- }
- function insert_dev(target, node, anchor) {
- dispatch_dev('SvelteDOMInsert', { target, node, anchor });
- insert(target, node, anchor);
- }
- function detach_dev(node) {
- dispatch_dev('SvelteDOMRemove', { node });
- detach(node);
- }
- function listen_dev(node, event, handler, options, has_prevent_default, has_stop_propagation, has_stop_immediate_propagation) {
- const modifiers = options === true ? ['capture'] : options ? Array.from(Object.keys(options)) : [];
- if (has_prevent_default)
- modifiers.push('preventDefault');
- if (has_stop_propagation)
- modifiers.push('stopPropagation');
- if (has_stop_immediate_propagation)
- modifiers.push('stopImmediatePropagation');
- dispatch_dev('SvelteDOMAddEventListener', { node, event, handler, modifiers });
- const dispose = listen(node, event, handler, options);
- return () => {
- dispatch_dev('SvelteDOMRemoveEventListener', { node, event, handler, modifiers });
- dispose();
- };
- }
- function attr_dev(node, attribute, value) {
- attr(node, attribute, value);
- if (value == null)
- dispatch_dev('SvelteDOMRemoveAttribute', { node, attribute });
- else
- dispatch_dev('SvelteDOMSetAttribute', { node, attribute, value });
- }
- function prop_dev(node, property, value) {
- node[property] = value;
- dispatch_dev('SvelteDOMSetProperty', { node, property, value });
- }
- function set_data_dev(text, data) {
- data = '' + data;
- if (text.data === data)
- return;
- dispatch_dev('SvelteDOMSetData', { node: text, data });
- text.data = data;
- }
- function validate_each_argument(arg) {
- if (typeof arg !== 'string' && !(arg && typeof arg === 'object' && 'length' in arg)) {
- let msg = '{#each} only iterates over array-like objects.';
- if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) {
- msg += ' You can use a spread to convert this iterable into an array.';
- }
- throw new Error(msg);
- }
- }
- function validate_slots(name, slot, keys) {
- for (const slot_key of Object.keys(slot)) {
- if (!~keys.indexOf(slot_key)) {
- console.warn(`<${name}> received an unexpected slot "${slot_key}".`);
- }
- }
- }
- function construct_svelte_component_dev(component, props) {
- const error_message = 'this={...} of should specify a Svelte component.';
- try {
- const instance = new component(props);
- if (!instance.$$ || !instance.$set || !instance.$on || !instance.$destroy) {
- throw new Error(error_message);
- }
- return instance;
- }
- catch (err) {
- const { message } = err;
- if (typeof message === 'string' && message.indexOf('is not a constructor') !== -1) {
- throw new Error(error_message);
- }
- else {
- throw err;
- }
- }
- }
- /**
- * Base class for Svelte components with some minor dev-enhancements. Used when dev=true.
- */
- class SvelteComponentDev extends SvelteComponent {
- constructor(options) {
- if (!options || (!options.target && !options.$$inline)) {
- throw new Error("'target' is a required option");
- }
- super();
- }
- $destroy() {
- super.$destroy();
- this.$destroy = () => {
- console.warn('Component was already destroyed'); // eslint-disable-line no-console
- };
- }
- $capture_state() { }
- $inject_state() { }
- }
-
- /**
- * @license
- * Copyright 2017 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- /**
- * @license
- * Copyright 2017 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const stringToByteArray$1 = function (str) {
- // TODO(user): Use native implementations if/when available
- const out = [];
- let p = 0;
- for (let i = 0; i < str.length; i++) {
- let c = str.charCodeAt(i);
- if (c < 128) {
- out[p++] = c;
- }
- else if (c < 2048) {
- out[p++] = (c >> 6) | 192;
- out[p++] = (c & 63) | 128;
- }
- else if ((c & 0xfc00) === 0xd800 &&
- i + 1 < str.length &&
- (str.charCodeAt(i + 1) & 0xfc00) === 0xdc00) {
- // Surrogate Pair
- c = 0x10000 + ((c & 0x03ff) << 10) + (str.charCodeAt(++i) & 0x03ff);
- out[p++] = (c >> 18) | 240;
- out[p++] = ((c >> 12) & 63) | 128;
- out[p++] = ((c >> 6) & 63) | 128;
- out[p++] = (c & 63) | 128;
- }
- else {
- out[p++] = (c >> 12) | 224;
- out[p++] = ((c >> 6) & 63) | 128;
- out[p++] = (c & 63) | 128;
- }
- }
- return out;
- };
- /**
- * Turns an array of numbers into the string given by the concatenation of the
- * characters to which the numbers correspond.
- * @param bytes Array of numbers representing characters.
- * @return Stringification of the array.
- */
- const byteArrayToString = function (bytes) {
- // TODO(user): Use native implementations if/when available
- const out = [];
- let pos = 0, c = 0;
- while (pos < bytes.length) {
- const c1 = bytes[pos++];
- if (c1 < 128) {
- out[c++] = String.fromCharCode(c1);
- }
- else if (c1 > 191 && c1 < 224) {
- const c2 = bytes[pos++];
- out[c++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
- }
- else if (c1 > 239 && c1 < 365) {
- // Surrogate Pair
- const c2 = bytes[pos++];
- const c3 = bytes[pos++];
- const c4 = bytes[pos++];
- const u = (((c1 & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63)) -
- 0x10000;
- out[c++] = String.fromCharCode(0xd800 + (u >> 10));
- out[c++] = String.fromCharCode(0xdc00 + (u & 1023));
- }
- else {
- const c2 = bytes[pos++];
- const c3 = bytes[pos++];
- out[c++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
- }
- }
- return out.join('');
- };
- // We define it as an object literal instead of a class because a class compiled down to es5 can't
- // be treeshaked. https://github.com/rollup/rollup/issues/1691
- // Static lookup maps, lazily populated by init_()
- const base64 = {
- /**
- * Maps bytes to characters.
- */
- byteToCharMap_: null,
- /**
- * Maps characters to bytes.
- */
- charToByteMap_: null,
- /**
- * Maps bytes to websafe characters.
- * @private
- */
- byteToCharMapWebSafe_: null,
- /**
- * Maps websafe characters to bytes.
- * @private
- */
- charToByteMapWebSafe_: null,
- /**
- * Our default alphabet, shared between
- * ENCODED_VALS and ENCODED_VALS_WEBSAFE
- */
- ENCODED_VALS_BASE: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789',
- /**
- * Our default alphabet. Value 64 (=) is special; it means "nothing."
- */
- get ENCODED_VALS() {
- return this.ENCODED_VALS_BASE + '+/=';
- },
- /**
- * Our websafe alphabet.
- */
- get ENCODED_VALS_WEBSAFE() {
- return this.ENCODED_VALS_BASE + '-_.';
- },
- /**
- * Whether this browser supports the atob and btoa functions. This extension
- * started at Mozilla but is now implemented by many browsers. We use the
- * ASSUME_* variables to avoid pulling in the full useragent detection library
- * but still allowing the standard per-browser compilations.
- *
- */
- HAS_NATIVE_SUPPORT: typeof atob === 'function',
- /**
- * Base64-encode an array of bytes.
- *
- * @param input An array of bytes (numbers with
- * value in [0, 255]) to encode.
- * @param webSafe Boolean indicating we should use the
- * alternative alphabet.
- * @return The base64 encoded string.
- */
- encodeByteArray(input, webSafe) {
- if (!Array.isArray(input)) {
- throw Error('encodeByteArray takes an array as a parameter');
- }
- this.init_();
- const byteToCharMap = webSafe
- ? this.byteToCharMapWebSafe_
- : this.byteToCharMap_;
- const output = [];
- for (let i = 0; i < input.length; i += 3) {
- const byte1 = input[i];
- const haveByte2 = i + 1 < input.length;
- const byte2 = haveByte2 ? input[i + 1] : 0;
- const haveByte3 = i + 2 < input.length;
- const byte3 = haveByte3 ? input[i + 2] : 0;
- const outByte1 = byte1 >> 2;
- const outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4);
- let outByte3 = ((byte2 & 0x0f) << 2) | (byte3 >> 6);
- let outByte4 = byte3 & 0x3f;
- if (!haveByte3) {
- outByte4 = 64;
- if (!haveByte2) {
- outByte3 = 64;
- }
- }
- output.push(byteToCharMap[outByte1], byteToCharMap[outByte2], byteToCharMap[outByte3], byteToCharMap[outByte4]);
- }
- return output.join('');
- },
- /**
- * Base64-encode a string.
- *
- * @param input A string to encode.
- * @param webSafe If true, we should use the
- * alternative alphabet.
- * @return The base64 encoded string.
- */
- encodeString(input, webSafe) {
- // Shortcut for Mozilla browsers that implement
- // a native base64 encoder in the form of "btoa/atob"
- if (this.HAS_NATIVE_SUPPORT && !webSafe) {
- return btoa(input);
- }
- return this.encodeByteArray(stringToByteArray$1(input), webSafe);
- },
- /**
- * Base64-decode a string.
- *
- * @param input to decode.
- * @param webSafe True if we should use the
- * alternative alphabet.
- * @return string representing the decoded value.
- */
- decodeString(input, webSafe) {
- // Shortcut for Mozilla browsers that implement
- // a native base64 encoder in the form of "btoa/atob"
- if (this.HAS_NATIVE_SUPPORT && !webSafe) {
- return atob(input);
- }
- return byteArrayToString(this.decodeStringToByteArray(input, webSafe));
- },
- /**
- * Base64-decode a string.
- *
- * In base-64 decoding, groups of four characters are converted into three
- * bytes. If the encoder did not apply padding, the input length may not
- * be a multiple of 4.
- *
- * In this case, the last group will have fewer than 4 characters, and
- * padding will be inferred. If the group has one or two characters, it decodes
- * to one byte. If the group has three characters, it decodes to two bytes.
- *
- * @param input Input to decode.
- * @param webSafe True if we should use the web-safe alphabet.
- * @return bytes representing the decoded value.
- */
- decodeStringToByteArray(input, webSafe) {
- this.init_();
- const charToByteMap = webSafe
- ? this.charToByteMapWebSafe_
- : this.charToByteMap_;
- const output = [];
- for (let i = 0; i < input.length;) {
- const byte1 = charToByteMap[input.charAt(i++)];
- const haveByte2 = i < input.length;
- const byte2 = haveByte2 ? charToByteMap[input.charAt(i)] : 0;
- ++i;
- const haveByte3 = i < input.length;
- const byte3 = haveByte3 ? charToByteMap[input.charAt(i)] : 64;
- ++i;
- const haveByte4 = i < input.length;
- const byte4 = haveByte4 ? charToByteMap[input.charAt(i)] : 64;
- ++i;
- if (byte1 == null || byte2 == null || byte3 == null || byte4 == null) {
- throw new DecodeBase64StringError();
- }
- const outByte1 = (byte1 << 2) | (byte2 >> 4);
- output.push(outByte1);
- if (byte3 !== 64) {
- const outByte2 = ((byte2 << 4) & 0xf0) | (byte3 >> 2);
- output.push(outByte2);
- if (byte4 !== 64) {
- const outByte3 = ((byte3 << 6) & 0xc0) | byte4;
- output.push(outByte3);
- }
- }
- }
- return output;
- },
- /**
- * Lazy static initialization function. Called before
- * accessing any of the static map variables.
- * @private
- */
- init_() {
- if (!this.byteToCharMap_) {
- this.byteToCharMap_ = {};
- this.charToByteMap_ = {};
- this.byteToCharMapWebSafe_ = {};
- this.charToByteMapWebSafe_ = {};
- // We want quick mappings back and forth, so we precompute two maps.
- for (let i = 0; i < this.ENCODED_VALS.length; i++) {
- this.byteToCharMap_[i] = this.ENCODED_VALS.charAt(i);
- this.charToByteMap_[this.byteToCharMap_[i]] = i;
- this.byteToCharMapWebSafe_[i] = this.ENCODED_VALS_WEBSAFE.charAt(i);
- this.charToByteMapWebSafe_[this.byteToCharMapWebSafe_[i]] = i;
- // Be forgiving when decoding and correctly decode both encodings.
- if (i >= this.ENCODED_VALS_BASE.length) {
- this.charToByteMap_[this.ENCODED_VALS_WEBSAFE.charAt(i)] = i;
- this.charToByteMapWebSafe_[this.ENCODED_VALS.charAt(i)] = i;
- }
- }
- }
- }
- };
- /**
- * An error encountered while decoding base64 string.
- */
- class DecodeBase64StringError extends Error {
- constructor() {
- super(...arguments);
- this.name = 'DecodeBase64StringError';
- }
- }
- /**
- * URL-safe base64 encoding
- */
- const base64Encode = function (str) {
- const utf8Bytes = stringToByteArray$1(str);
- return base64.encodeByteArray(utf8Bytes, true);
- };
- /**
- * URL-safe base64 encoding (without "." padding in the end).
- * e.g. Used in JSON Web Token (JWT) parts.
- */
- const base64urlEncodeWithoutPadding = function (str) {
- // Use base64url encoding and remove padding in the end (dot characters).
- return base64Encode(str).replace(/\./g, '');
- };
- /**
- * URL-safe base64 decoding
- *
- * NOTE: DO NOT use the global atob() function - it does NOT support the
- * base64Url variant encoding.
- *
- * @param str To be decoded
- * @return Decoded result, if possible
- */
- const base64Decode = function (str) {
- try {
- return base64.decodeString(str, true);
- }
- catch (e) {
- console.error('base64Decode failed: ', e);
- }
- return null;
- };
- /**
- * Copy properties from source to target (recursively allows extension
- * of Objects and Arrays). Scalar values in the target are over-written.
- * If target is undefined, an object of the appropriate type will be created
- * (and returned).
- *
- * We recursively copy all child properties of plain Objects in the source- so
- * that namespace- like dictionaries are merged.
- *
- * Note that the target can be a function, in which case the properties in
- * the source Object are copied onto it as static properties of the Function.
- *
- * Note: we don't merge __proto__ to prevent prototype pollution
- */
- function deepExtend(target, source) {
- if (!(source instanceof Object)) {
- return source;
- }
- switch (source.constructor) {
- case Date:
- // Treat Dates like scalars; if the target date object had any child
- // properties - they will be lost!
- const dateValue = source;
- return new Date(dateValue.getTime());
- case Object:
- if (target === undefined) {
- target = {};
- }
- break;
- case Array:
- // Always copy the array source and overwrite the target.
- target = [];
- break;
- default:
- // Not a plain Object - treat it as a scalar.
- return source;
- }
- for (const prop in source) {
- // use isValidKey to guard against prototype pollution. See https://snyk.io/vuln/SNYK-JS-LODASH-450202
- if (!source.hasOwnProperty(prop) || !isValidKey(prop)) {
- continue;
- }
- target[prop] = deepExtend(target[prop], source[prop]);
- }
- return target;
- }
- function isValidKey(key) {
- return key !== '__proto__';
- }
-
- /**
- * @license
- * Copyright 2022 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Polyfill for `globalThis` object.
- * @returns the `globalThis` object for the given environment.
- * @public
- */
- function getGlobal() {
- if (typeof self !== 'undefined') {
- return self;
- }
- if (typeof window !== 'undefined') {
- return window;
- }
- if (typeof global !== 'undefined') {
- return global;
- }
- throw new Error('Unable to locate global object.');
- }
-
- /**
- * @license
- * Copyright 2022 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const getDefaultsFromGlobal = () => getGlobal().__FIREBASE_DEFAULTS__;
- /**
- * Attempt to read defaults from a JSON string provided to
- * process(.)env(.)__FIREBASE_DEFAULTS__ or a JSON file whose path is in
- * process(.)env(.)__FIREBASE_DEFAULTS_PATH__
- * The dots are in parens because certain compilers (Vite?) cannot
- * handle seeing that variable in comments.
- * See https://github.com/firebase/firebase-js-sdk/issues/6838
- */
- const getDefaultsFromEnvVariable = () => {
- if (typeof process === 'undefined' || typeof process.env === 'undefined') {
- return;
- }
- const defaultsJsonString = process.env.__FIREBASE_DEFAULTS__;
- if (defaultsJsonString) {
- return JSON.parse(defaultsJsonString);
- }
- };
- const getDefaultsFromCookie = () => {
- if (typeof document === 'undefined') {
- return;
- }
- let match;
- try {
- match = document.cookie.match(/__FIREBASE_DEFAULTS__=([^;]+)/);
- }
- catch (e) {
- // Some environments such as Angular Universal SSR have a
- // `document` object but error on accessing `document.cookie`.
- return;
- }
- const decoded = match && base64Decode(match[1]);
- return decoded && JSON.parse(decoded);
- };
- /**
- * Get the __FIREBASE_DEFAULTS__ object. It checks in order:
- * (1) if such an object exists as a property of `globalThis`
- * (2) if such an object was provided on a shell environment variable
- * (3) if such an object exists in a cookie
- * @public
- */
- const getDefaults = () => {
- try {
- return (getDefaultsFromGlobal() ||
- getDefaultsFromEnvVariable() ||
- getDefaultsFromCookie());
- }
- catch (e) {
- /**
- * Catch-all for being unable to get __FIREBASE_DEFAULTS__ due
- * to any environment case we have not accounted for. Log to
- * info instead of swallowing so we can find these unknown cases
- * and add paths for them if needed.
- */
- console.info(`Unable to get __FIREBASE_DEFAULTS__ due to: ${e}`);
- return;
- }
- };
- /**
- * Returns emulator host stored in the __FIREBASE_DEFAULTS__ object
- * for the given product.
- * @returns a URL host formatted like `127.0.0.1:9999` or `[::1]:4000` if available
- * @public
- */
- const getDefaultEmulatorHost = (productName) => { var _a, _b; return (_b = (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.emulatorHosts) === null || _b === void 0 ? void 0 : _b[productName]; };
- /**
- * Returns emulator hostname and port stored in the __FIREBASE_DEFAULTS__ object
- * for the given product.
- * @returns a pair of hostname and port like `["::1", 4000]` if available
- * @public
- */
- const getDefaultEmulatorHostnameAndPort = (productName) => {
- const host = getDefaultEmulatorHost(productName);
- if (!host) {
- return undefined;
- }
- const separatorIndex = host.lastIndexOf(':'); // Finding the last since IPv6 addr also has colons.
- if (separatorIndex <= 0 || separatorIndex + 1 === host.length) {
- throw new Error(`Invalid host ${host} with no separate hostname and port!`);
- }
- // eslint-disable-next-line no-restricted-globals
- const port = parseInt(host.substring(separatorIndex + 1), 10);
- if (host[0] === '[') {
- // Bracket-quoted `[ipv6addr]:port` => return "ipv6addr" (without brackets).
- return [host.substring(1, separatorIndex - 1), port];
- }
- else {
- return [host.substring(0, separatorIndex), port];
- }
- };
- /**
- * Returns Firebase app config stored in the __FIREBASE_DEFAULTS__ object.
- * @public
- */
- const getDefaultAppConfig = () => { var _a; return (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.config; };
- /**
- * Returns an experimental setting on the __FIREBASE_DEFAULTS__ object (properties
- * prefixed by "_")
- * @public
- */
- const getExperimentalSetting = (name) => { var _a; return (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a[`_${name}`]; };
-
- /**
- * @license
- * Copyright 2017 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class Deferred {
- constructor() {
- this.reject = () => { };
- this.resolve = () => { };
- this.promise = new Promise((resolve, reject) => {
- this.resolve = resolve;
- this.reject = reject;
- });
- }
- /**
- * Our API internals are not promiseified and cannot because our callback APIs have subtle expectations around
- * invoking promises inline, which Promises are forbidden to do. This method accepts an optional node-style callback
- * and returns a node-style callback which will resolve or reject the Deferred's promise.
- */
- wrapCallback(callback) {
- return (error, value) => {
- if (error) {
- this.reject(error);
- }
- else {
- this.resolve(value);
- }
- if (typeof callback === 'function') {
- // Attaching noop handler just in case developer wasn't expecting
- // promises
- this.promise.catch(() => { });
- // Some of our callbacks don't expect a value and our own tests
- // assert that the parameter length is 1
- if (callback.length === 1) {
- callback(error);
- }
- else {
- callback(error, value);
- }
- }
- };
- }
- }
-
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function createMockUserToken(token, projectId) {
- if (token.uid) {
- throw new Error('The "uid" field is no longer supported by mockUserToken. Please use "sub" instead for Firebase Auth User ID.');
- }
- // Unsecured JWTs use "none" as the algorithm.
- const header = {
- alg: 'none',
- type: 'JWT'
- };
- const project = projectId || 'demo-project';
- const iat = token.iat || 0;
- const sub = token.sub || token.user_id;
- if (!sub) {
- throw new Error("mockUserToken must contain 'sub' or 'user_id' field!");
- }
- const payload = Object.assign({
- // Set all required fields to decent defaults
- iss: `https://securetoken.google.com/${project}`, aud: project, iat, exp: iat + 3600, auth_time: iat, sub, user_id: sub, firebase: {
- sign_in_provider: 'custom',
- identities: {}
- } }, token);
- // Unsecured JWTs use the empty string as a signature.
- const signature = '';
- return [
- base64urlEncodeWithoutPadding(JSON.stringify(header)),
- base64urlEncodeWithoutPadding(JSON.stringify(payload)),
- signature
- ].join('.');
- }
-
- /**
- * @license
- * Copyright 2017 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Returns navigator.userAgent string or '' if it's not defined.
- * @return user agent string
- */
- function getUA() {
- if (typeof navigator !== 'undefined' &&
- typeof navigator['userAgent'] === 'string') {
- return navigator['userAgent'];
- }
- else {
- return '';
- }
- }
- /**
- * Detect Cordova / PhoneGap / Ionic frameworks on a mobile device.
- *
- * Deliberately does not rely on checking `file://` URLs (as this fails PhoneGap
- * in the Ripple emulator) nor Cordova `onDeviceReady`, which would normally
- * wait for a callback.
- */
- function isMobileCordova() {
- return (typeof window !== 'undefined' &&
- // @ts-ignore Setting up an broadly applicable index signature for Window
- // just to deal with this case would probably be a bad idea.
- !!(window['cordova'] || window['phonegap'] || window['PhoneGap']) &&
- /ios|iphone|ipod|ipad|android|blackberry|iemobile/i.test(getUA()));
- }
- /**
- * Detect Node.js.
- *
- * @return true if Node.js environment is detected or specified.
- */
- // Node detection logic from: https://github.com/iliakan/detect-node/
- function isNode() {
- var _a;
- const forceEnvironment = (_a = getDefaults()) === null || _a === void 0 ? void 0 : _a.forceEnvironment;
- if (forceEnvironment === 'node') {
- return true;
- }
- else if (forceEnvironment === 'browser') {
- return false;
- }
- try {
- return (Object.prototype.toString.call(global.process) === '[object process]');
- }
- catch (e) {
- return false;
- }
- }
- /**
- * Detect Browser Environment
- */
- function isBrowser() {
- return typeof self === 'object' && self.self === self;
- }
- function isBrowserExtension() {
- const runtime = typeof chrome === 'object'
- ? chrome.runtime
- : typeof browser === 'object'
- ? browser.runtime
- : undefined;
- return typeof runtime === 'object' && runtime.id !== undefined;
- }
- /**
- * Detect React Native.
- *
- * @return true if ReactNative environment is detected.
- */
- function isReactNative() {
- return (typeof navigator === 'object' && navigator['product'] === 'ReactNative');
- }
- /** Detects Internet Explorer. */
- function isIE() {
- const ua = getUA();
- return ua.indexOf('MSIE ') >= 0 || ua.indexOf('Trident/') >= 0;
- }
- /** Returns true if we are running in Safari. */
- function isSafari() {
- return (!isNode() &&
- navigator.userAgent.includes('Safari') &&
- !navigator.userAgent.includes('Chrome'));
- }
- /**
- * This method checks if indexedDB is supported by current browser/service worker context
- * @return true if indexedDB is supported by current browser/service worker context
- */
- function isIndexedDBAvailable() {
- try {
- return typeof indexedDB === 'object';
- }
- catch (e) {
- return false;
- }
- }
- /**
- * This method validates browser/sw context for indexedDB by opening a dummy indexedDB database and reject
- * if errors occur during the database open operation.
- *
- * @throws exception if current browser/sw context can't run idb.open (ex: Safari iframe, Firefox
- * private browsing)
- */
- function validateIndexedDBOpenable() {
- return new Promise((resolve, reject) => {
- try {
- let preExist = true;
- const DB_CHECK_NAME = 'validate-browser-context-for-indexeddb-analytics-module';
- const request = self.indexedDB.open(DB_CHECK_NAME);
- request.onsuccess = () => {
- request.result.close();
- // delete database only when it doesn't pre-exist
- if (!preExist) {
- self.indexedDB.deleteDatabase(DB_CHECK_NAME);
- }
- resolve(true);
- };
- request.onupgradeneeded = () => {
- preExist = false;
- };
- request.onerror = () => {
- var _a;
- reject(((_a = request.error) === null || _a === void 0 ? void 0 : _a.message) || '');
- };
- }
- catch (error) {
- reject(error);
- }
- });
- }
- /**
- *
- * This method checks whether cookie is enabled within current browser
- * @return true if cookie is enabled within current browser
- */
- function areCookiesEnabled() {
- if (typeof navigator === 'undefined' || !navigator.cookieEnabled) {
- return false;
- }
- return true;
- }
-
- /**
- * @license
- * Copyright 2017 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * @fileoverview Standardized Firebase Error.
- *
- * Usage:
- *
- * // Typescript string literals for type-safe codes
- * type Err =
- * 'unknown' |
- * 'object-not-found'
- * ;
- *
- * // Closure enum for type-safe error codes
- * // at-enum {string}
- * var Err = {
- * UNKNOWN: 'unknown',
- * OBJECT_NOT_FOUND: 'object-not-found',
- * }
- *
- * let errors: Map = {
- * 'generic-error': "Unknown error",
- * 'file-not-found': "Could not find file: {$file}",
- * };
- *
- * // Type-safe function - must pass a valid error code as param.
- * let error = new ErrorFactory('service', 'Service', errors);
- *
- * ...
- * throw error.create(Err.GENERIC);
- * ...
- * throw error.create(Err.FILE_NOT_FOUND, {'file': fileName});
- * ...
- * // Service: Could not file file: foo.txt (service/file-not-found).
- *
- * catch (e) {
- * assert(e.message === "Could not find file: foo.txt.");
- * if ((e as FirebaseError)?.code === 'service/file-not-found') {
- * console.log("Could not read file: " + e['file']);
- * }
- * }
- */
- const ERROR_NAME = 'FirebaseError';
- // Based on code from:
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Custom_Error_Types
- class FirebaseError extends Error {
- constructor(
- /** The error code for this error. */
- code, message,
- /** Custom data for this error. */
- customData) {
- super(message);
- this.code = code;
- this.customData = customData;
- /** The custom name for all FirebaseErrors. */
- this.name = ERROR_NAME;
- // Fix For ES5
- // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
- Object.setPrototypeOf(this, FirebaseError.prototype);
- // Maintains proper stack trace for where our error was thrown.
- // Only available on V8.
- if (Error.captureStackTrace) {
- Error.captureStackTrace(this, ErrorFactory.prototype.create);
- }
- }
- }
- class ErrorFactory {
- constructor(service, serviceName, errors) {
- this.service = service;
- this.serviceName = serviceName;
- this.errors = errors;
- }
- create(code, ...data) {
- const customData = data[0] || {};
- const fullCode = `${this.service}/${code}`;
- const template = this.errors[code];
- const message = template ? replaceTemplate(template, customData) : 'Error';
- // Service Name: Error message (service/code).
- const fullMessage = `${this.serviceName}: ${message} (${fullCode}).`;
- const error = new FirebaseError(fullCode, fullMessage, customData);
- return error;
- }
- }
- function replaceTemplate(template, data) {
- return template.replace(PATTERN, (_, key) => {
- const value = data[key];
- return value != null ? String(value) : `<${key}?>`;
- });
- }
- const PATTERN = /\{\$([^}]+)}/g;
-
- /**
- * @license
- * Copyright 2017 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function contains$1(obj, key) {
- return Object.prototype.hasOwnProperty.call(obj, key);
- }
- function isEmpty(obj) {
- for (const key in obj) {
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
- return false;
- }
- }
- return true;
- }
- /**
- * Deep equal two objects. Support Arrays and Objects.
- */
- function deepEqual(a, b) {
- if (a === b) {
- return true;
- }
- const aKeys = Object.keys(a);
- const bKeys = Object.keys(b);
- for (const k of aKeys) {
- if (!bKeys.includes(k)) {
- return false;
- }
- const aProp = a[k];
- const bProp = b[k];
- if (isObject(aProp) && isObject(bProp)) {
- if (!deepEqual(aProp, bProp)) {
- return false;
- }
- }
- else if (aProp !== bProp) {
- return false;
- }
- }
- for (const k of bKeys) {
- if (!aKeys.includes(k)) {
- return false;
- }
- }
- return true;
- }
- function isObject(thing) {
- return thing !== null && typeof thing === 'object';
- }
-
- /**
- * @license
- * Copyright 2017 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Returns a querystring-formatted string (e.g. &arg=val&arg2=val2) from a
- * params object (e.g. {arg: 'val', arg2: 'val2'})
- * Note: You must prepend it with ? when adding it to a URL.
- */
- function querystring(querystringParams) {
- const params = [];
- for (const [key, value] of Object.entries(querystringParams)) {
- if (Array.isArray(value)) {
- value.forEach(arrayVal => {
- params.push(encodeURIComponent(key) + '=' + encodeURIComponent(arrayVal));
- });
- }
- else {
- params.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
- }
- }
- return params.length ? '&' + params.join('&') : '';
- }
- /**
- * Decodes a querystring (e.g. ?arg=val&arg2=val2) into a params object
- * (e.g. {arg: 'val', arg2: 'val2'})
- */
- function querystringDecode(querystring) {
- const obj = {};
- const tokens = querystring.replace(/^\?/, '').split('&');
- tokens.forEach(token => {
- if (token) {
- const [key, value] = token.split('=');
- obj[decodeURIComponent(key)] = decodeURIComponent(value);
- }
- });
- return obj;
- }
- /**
- * Extract the query string part of a URL, including the leading question mark (if present).
- */
- function extractQuerystring(url) {
- const queryStart = url.indexOf('?');
- if (!queryStart) {
- return '';
- }
- const fragmentStart = url.indexOf('#', queryStart);
- return url.substring(queryStart, fragmentStart > 0 ? fragmentStart : undefined);
- }
-
- /**
- * Helper to make a Subscribe function (just like Promise helps make a
- * Thenable).
- *
- * @param executor Function which can make calls to a single Observer
- * as a proxy.
- * @param onNoObservers Callback when count of Observers goes to zero.
- */
- function createSubscribe(executor, onNoObservers) {
- const proxy = new ObserverProxy(executor, onNoObservers);
- return proxy.subscribe.bind(proxy);
- }
- /**
- * Implement fan-out for any number of Observers attached via a subscribe
- * function.
- */
- class ObserverProxy {
- /**
- * @param executor Function which can make calls to a single Observer
- * as a proxy.
- * @param onNoObservers Callback when count of Observers goes to zero.
- */
- constructor(executor, onNoObservers) {
- this.observers = [];
- this.unsubscribes = [];
- this.observerCount = 0;
- // Micro-task scheduling by calling task.then().
- this.task = Promise.resolve();
- this.finalized = false;
- this.onNoObservers = onNoObservers;
- // Call the executor asynchronously so subscribers that are called
- // synchronously after the creation of the subscribe function
- // can still receive the very first value generated in the executor.
- this.task
- .then(() => {
- executor(this);
- })
- .catch(e => {
- this.error(e);
- });
- }
- next(value) {
- this.forEachObserver((observer) => {
- observer.next(value);
- });
- }
- error(error) {
- this.forEachObserver((observer) => {
- observer.error(error);
- });
- this.close(error);
- }
- complete() {
- this.forEachObserver((observer) => {
- observer.complete();
- });
- this.close();
- }
- /**
- * Subscribe function that can be used to add an Observer to the fan-out list.
- *
- * - We require that no event is sent to a subscriber sychronously to their
- * call to subscribe().
- */
- subscribe(nextOrObserver, error, complete) {
- let observer;
- if (nextOrObserver === undefined &&
- error === undefined &&
- complete === undefined) {
- throw new Error('Missing Observer.');
- }
- // Assemble an Observer object when passed as callback functions.
- if (implementsAnyMethods$1(nextOrObserver, [
- 'next',
- 'error',
- 'complete'
- ])) {
- observer = nextOrObserver;
- }
- else {
- observer = {
- next: nextOrObserver,
- error,
- complete
- };
- }
- if (observer.next === undefined) {
- observer.next = noop;
- }
- if (observer.error === undefined) {
- observer.error = noop;
- }
- if (observer.complete === undefined) {
- observer.complete = noop;
- }
- const unsub = this.unsubscribeOne.bind(this, this.observers.length);
- // Attempt to subscribe to a terminated Observable - we
- // just respond to the Observer with the final error or complete
- // event.
- if (this.finalized) {
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- this.task.then(() => {
- try {
- if (this.finalError) {
- observer.error(this.finalError);
- }
- else {
- observer.complete();
- }
- }
- catch (e) {
- // nothing
- }
- return;
- });
- }
- this.observers.push(observer);
- return unsub;
- }
- // Unsubscribe is synchronous - we guarantee that no events are sent to
- // any unsubscribed Observer.
- unsubscribeOne(i) {
- if (this.observers === undefined || this.observers[i] === undefined) {
- return;
- }
- delete this.observers[i];
- this.observerCount -= 1;
- if (this.observerCount === 0 && this.onNoObservers !== undefined) {
- this.onNoObservers(this);
- }
- }
- forEachObserver(fn) {
- if (this.finalized) {
- // Already closed by previous event....just eat the additional values.
- return;
- }
- // Since sendOne calls asynchronously - there is no chance that
- // this.observers will become undefined.
- for (let i = 0; i < this.observers.length; i++) {
- this.sendOne(i, fn);
- }
- }
- // Call the Observer via one of it's callback function. We are careful to
- // confirm that the observe has not been unsubscribed since this asynchronous
- // function had been queued.
- sendOne(i, fn) {
- // Execute the callback asynchronously
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- this.task.then(() => {
- if (this.observers !== undefined && this.observers[i] !== undefined) {
- try {
- fn(this.observers[i]);
- }
- catch (e) {
- // Ignore exceptions raised in Observers or missing methods of an
- // Observer.
- // Log error to console. b/31404806
- if (typeof console !== 'undefined' && console.error) {
- console.error(e);
- }
- }
- }
- });
- }
- close(err) {
- if (this.finalized) {
- return;
- }
- this.finalized = true;
- if (err !== undefined) {
- this.finalError = err;
- }
- // Proxy is no longer needed - garbage collect references
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- this.task.then(() => {
- this.observers = undefined;
- this.onNoObservers = undefined;
- });
- }
- }
- /**
- * Return true if the object passed in implements any of the named methods.
- */
- function implementsAnyMethods$1(obj, methods) {
- if (typeof obj !== 'object' || obj === null) {
- return false;
- }
- for (const method of methods) {
- if (method in obj && typeof obj[method] === 'function') {
- return true;
- }
- }
- return false;
- }
- function noop() {
- // do nothing
- }
-
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function getModularInstance(service) {
- if (service && service._delegate) {
- return service._delegate;
- }
- else {
- return service;
- }
- }
-
- /**
- * Component for service name T, e.g. `auth`, `auth-internal`
- */
- class Component {
- /**
- *
- * @param name The public service name, e.g. app, auth, firestore, database
- * @param instanceFactory Service factory responsible for creating the public interface
- * @param type whether the service provided by the component is public or private
- */
- constructor(name, instanceFactory, type) {
- this.name = name;
- this.instanceFactory = instanceFactory;
- this.type = type;
- this.multipleInstances = false;
- /**
- * Properties to be added to the service namespace
- */
- this.serviceProps = {};
- this.instantiationMode = "LAZY" /* InstantiationMode.LAZY */;
- this.onInstanceCreated = null;
- }
- setInstantiationMode(mode) {
- this.instantiationMode = mode;
- return this;
- }
- setMultipleInstances(multipleInstances) {
- this.multipleInstances = multipleInstances;
- return this;
- }
- setServiceProps(props) {
- this.serviceProps = props;
- return this;
- }
- setInstanceCreatedCallback(callback) {
- this.onInstanceCreated = callback;
- return this;
- }
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const DEFAULT_ENTRY_NAME$2 = '[DEFAULT]';
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for instance for service name T, e.g. 'auth', 'auth-internal'
- * NameServiceMapping[T] is an alias for the type of the instance
- */
- class Provider {
- constructor(name, container) {
- this.name = name;
- this.container = container;
- this.component = null;
- this.instances = new Map();
- this.instancesDeferred = new Map();
- this.instancesOptions = new Map();
- this.onInitCallbacks = new Map();
- }
- /**
- * @param identifier A provider can provide mulitple instances of a service
- * if this.component.multipleInstances is true.
- */
- get(identifier) {
- // if multipleInstances is not supported, use the default name
- const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
- if (!this.instancesDeferred.has(normalizedIdentifier)) {
- const deferred = new Deferred();
- this.instancesDeferred.set(normalizedIdentifier, deferred);
- if (this.isInitialized(normalizedIdentifier) ||
- this.shouldAutoInitialize()) {
- // initialize the service if it can be auto-initialized
- try {
- const instance = this.getOrInitializeService({
- instanceIdentifier: normalizedIdentifier
- });
- if (instance) {
- deferred.resolve(instance);
- }
- }
- catch (e) {
- // when the instance factory throws an exception during get(), it should not cause
- // a fatal error. We just return the unresolved promise in this case.
- }
- }
- }
- return this.instancesDeferred.get(normalizedIdentifier).promise;
- }
- getImmediate(options) {
- var _a;
- // if multipleInstances is not supported, use the default name
- const normalizedIdentifier = this.normalizeInstanceIdentifier(options === null || options === void 0 ? void 0 : options.identifier);
- const optional = (_a = options === null || options === void 0 ? void 0 : options.optional) !== null && _a !== void 0 ? _a : false;
- if (this.isInitialized(normalizedIdentifier) ||
- this.shouldAutoInitialize()) {
- try {
- return this.getOrInitializeService({
- instanceIdentifier: normalizedIdentifier
- });
- }
- catch (e) {
- if (optional) {
- return null;
- }
- else {
- throw e;
- }
- }
- }
- else {
- // In case a component is not initialized and should/can not be auto-initialized at the moment, return null if the optional flag is set, or throw
- if (optional) {
- return null;
- }
- else {
- throw Error(`Service ${this.name} is not available`);
- }
- }
- }
- getComponent() {
- return this.component;
- }
- setComponent(component) {
- if (component.name !== this.name) {
- throw Error(`Mismatching Component ${component.name} for Provider ${this.name}.`);
- }
- if (this.component) {
- throw Error(`Component for ${this.name} has already been provided`);
- }
- this.component = component;
- // return early without attempting to initialize the component if the component requires explicit initialization (calling `Provider.initialize()`)
- if (!this.shouldAutoInitialize()) {
- return;
- }
- // if the service is eager, initialize the default instance
- if (isComponentEager(component)) {
- try {
- this.getOrInitializeService({ instanceIdentifier: DEFAULT_ENTRY_NAME$2 });
- }
- catch (e) {
- // when the instance factory for an eager Component throws an exception during the eager
- // initialization, it should not cause a fatal error.
- // TODO: Investigate if we need to make it configurable, because some component may want to cause
- // a fatal error in this case?
- }
- }
- // Create service instances for the pending promises and resolve them
- // NOTE: if this.multipleInstances is false, only the default instance will be created
- // and all promises with resolve with it regardless of the identifier.
- for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
- const normalizedIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
- try {
- // `getOrInitializeService()` should always return a valid instance since a component is guaranteed. use ! to make typescript happy.
- const instance = this.getOrInitializeService({
- instanceIdentifier: normalizedIdentifier
- });
- instanceDeferred.resolve(instance);
- }
- catch (e) {
- // when the instance factory throws an exception, it should not cause
- // a fatal error. We just leave the promise unresolved.
- }
- }
- }
- clearInstance(identifier = DEFAULT_ENTRY_NAME$2) {
- this.instancesDeferred.delete(identifier);
- this.instancesOptions.delete(identifier);
- this.instances.delete(identifier);
- }
- // app.delete() will call this method on every provider to delete the services
- // TODO: should we mark the provider as deleted?
- async delete() {
- const services = Array.from(this.instances.values());
- await Promise.all([
- ...services
- .filter(service => 'INTERNAL' in service) // legacy services
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- .map(service => service.INTERNAL.delete()),
- ...services
- .filter(service => '_delete' in service) // modularized services
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- .map(service => service._delete())
- ]);
- }
- isComponentSet() {
- return this.component != null;
- }
- isInitialized(identifier = DEFAULT_ENTRY_NAME$2) {
- return this.instances.has(identifier);
- }
- getOptions(identifier = DEFAULT_ENTRY_NAME$2) {
- return this.instancesOptions.get(identifier) || {};
- }
- initialize(opts = {}) {
- const { options = {} } = opts;
- const normalizedIdentifier = this.normalizeInstanceIdentifier(opts.instanceIdentifier);
- if (this.isInitialized(normalizedIdentifier)) {
- throw Error(`${this.name}(${normalizedIdentifier}) has already been initialized`);
- }
- if (!this.isComponentSet()) {
- throw Error(`Component ${this.name} has not been registered yet`);
- }
- const instance = this.getOrInitializeService({
- instanceIdentifier: normalizedIdentifier,
- options
- });
- // resolve any pending promise waiting for the service instance
- for (const [instanceIdentifier, instanceDeferred] of this.instancesDeferred.entries()) {
- const normalizedDeferredIdentifier = this.normalizeInstanceIdentifier(instanceIdentifier);
- if (normalizedIdentifier === normalizedDeferredIdentifier) {
- instanceDeferred.resolve(instance);
- }
- }
- return instance;
- }
- /**
- *
- * @param callback - a function that will be invoked after the provider has been initialized by calling provider.initialize().
- * The function is invoked SYNCHRONOUSLY, so it should not execute any longrunning tasks in order to not block the program.
- *
- * @param identifier An optional instance identifier
- * @returns a function to unregister the callback
- */
- onInit(callback, identifier) {
- var _a;
- const normalizedIdentifier = this.normalizeInstanceIdentifier(identifier);
- const existingCallbacks = (_a = this.onInitCallbacks.get(normalizedIdentifier)) !== null && _a !== void 0 ? _a : new Set();
- existingCallbacks.add(callback);
- this.onInitCallbacks.set(normalizedIdentifier, existingCallbacks);
- const existingInstance = this.instances.get(normalizedIdentifier);
- if (existingInstance) {
- callback(existingInstance, normalizedIdentifier);
- }
- return () => {
- existingCallbacks.delete(callback);
- };
- }
- /**
- * Invoke onInit callbacks synchronously
- * @param instance the service instance`
- */
- invokeOnInitCallbacks(instance, identifier) {
- const callbacks = this.onInitCallbacks.get(identifier);
- if (!callbacks) {
- return;
- }
- for (const callback of callbacks) {
- try {
- callback(instance, identifier);
- }
- catch (_a) {
- // ignore errors in the onInit callback
- }
- }
- }
- getOrInitializeService({ instanceIdentifier, options = {} }) {
- let instance = this.instances.get(instanceIdentifier);
- if (!instance && this.component) {
- instance = this.component.instanceFactory(this.container, {
- instanceIdentifier: normalizeIdentifierForFactory(instanceIdentifier),
- options
- });
- this.instances.set(instanceIdentifier, instance);
- this.instancesOptions.set(instanceIdentifier, options);
- /**
- * Invoke onInit listeners.
- * Note this.component.onInstanceCreated is different, which is used by the component creator,
- * while onInit listeners are registered by consumers of the provider.
- */
- this.invokeOnInitCallbacks(instance, instanceIdentifier);
- /**
- * Order is important
- * onInstanceCreated() should be called after this.instances.set(instanceIdentifier, instance); which
- * makes `isInitialized()` return true.
- */
- if (this.component.onInstanceCreated) {
- try {
- this.component.onInstanceCreated(this.container, instanceIdentifier, instance);
- }
- catch (_a) {
- // ignore errors in the onInstanceCreatedCallback
- }
- }
- }
- return instance || null;
- }
- normalizeInstanceIdentifier(identifier = DEFAULT_ENTRY_NAME$2) {
- if (this.component) {
- return this.component.multipleInstances ? identifier : DEFAULT_ENTRY_NAME$2;
- }
- else {
- return identifier; // assume multiple instances are supported before the component is provided.
- }
- }
- shouldAutoInitialize() {
- return (!!this.component &&
- this.component.instantiationMode !== "EXPLICIT" /* InstantiationMode.EXPLICIT */);
- }
- }
- // undefined should be passed to the service factory for the default instance
- function normalizeIdentifierForFactory(identifier) {
- return identifier === DEFAULT_ENTRY_NAME$2 ? undefined : identifier;
- }
- function isComponentEager(component) {
- return component.instantiationMode === "EAGER" /* InstantiationMode.EAGER */;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * ComponentContainer that provides Providers for service name T, e.g. `auth`, `auth-internal`
- */
- class ComponentContainer {
- constructor(name) {
- this.name = name;
- this.providers = new Map();
- }
- /**
- *
- * @param component Component being added
- * @param overwrite When a component with the same name has already been registered,
- * if overwrite is true: overwrite the existing component with the new component and create a new
- * provider with the new component. It can be useful in tests where you want to use different mocks
- * for different tests.
- * if overwrite is false: throw an exception
- */
- addComponent(component) {
- const provider = this.getProvider(component.name);
- if (provider.isComponentSet()) {
- throw new Error(`Component ${component.name} has already been registered with ${this.name}`);
- }
- provider.setComponent(component);
- }
- addOrOverwriteComponent(component) {
- const provider = this.getProvider(component.name);
- if (provider.isComponentSet()) {
- // delete the existing provider from the container, so we can register the new component
- this.providers.delete(component.name);
- }
- this.addComponent(component);
- }
- /**
- * getProvider provides a type safe interface where it can only be called with a field name
- * present in NameServiceMapping interface.
- *
- * Firebase SDKs providing services should extend NameServiceMapping interface to register
- * themselves.
- */
- getProvider(name) {
- if (this.providers.has(name)) {
- return this.providers.get(name);
- }
- // create a Provider for a service that hasn't registered with Firebase
- const provider = new Provider(name, this);
- this.providers.set(name, provider);
- return provider;
- }
- getProviders() {
- return Array.from(this.providers.values());
- }
- }
-
- /**
- * @license
- * Copyright 2017 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * A container for all of the Logger instances
- */
- const instances = [];
- /**
- * The JS SDK supports 5 log levels and also allows a user the ability to
- * silence the logs altogether.
- *
- * The order is a follows:
- * DEBUG < VERBOSE < INFO < WARN < ERROR
- *
- * All of the log types above the current log level will be captured (i.e. if
- * you set the log level to `INFO`, errors will still be logged, but `DEBUG` and
- * `VERBOSE` logs will not)
- */
- var LogLevel;
- (function (LogLevel) {
- LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
- LogLevel[LogLevel["VERBOSE"] = 1] = "VERBOSE";
- LogLevel[LogLevel["INFO"] = 2] = "INFO";
- LogLevel[LogLevel["WARN"] = 3] = "WARN";
- LogLevel[LogLevel["ERROR"] = 4] = "ERROR";
- LogLevel[LogLevel["SILENT"] = 5] = "SILENT";
- })(LogLevel || (LogLevel = {}));
- const levelStringToEnum = {
- 'debug': LogLevel.DEBUG,
- 'verbose': LogLevel.VERBOSE,
- 'info': LogLevel.INFO,
- 'warn': LogLevel.WARN,
- 'error': LogLevel.ERROR,
- 'silent': LogLevel.SILENT
- };
- /**
- * The default log level
- */
- const defaultLogLevel = LogLevel.INFO;
- /**
- * By default, `console.debug` is not displayed in the developer console (in
- * chrome). To avoid forcing users to have to opt-in to these logs twice
- * (i.e. once for firebase, and once in the console), we are sending `DEBUG`
- * logs to the `console.log` function.
- */
- const ConsoleMethod = {
- [LogLevel.DEBUG]: 'log',
- [LogLevel.VERBOSE]: 'log',
- [LogLevel.INFO]: 'info',
- [LogLevel.WARN]: 'warn',
- [LogLevel.ERROR]: 'error'
- };
- /**
- * The default log handler will forward DEBUG, VERBOSE, INFO, WARN, and ERROR
- * messages on to their corresponding console counterparts (if the log method
- * is supported by the current log level)
- */
- const defaultLogHandler = (instance, logType, ...args) => {
- if (logType < instance.logLevel) {
- return;
- }
- const now = new Date().toISOString();
- const method = ConsoleMethod[logType];
- if (method) {
- console[method](`[${now}] ${instance.name}:`, ...args);
- }
- else {
- throw new Error(`Attempted to log a message with an invalid logType (value: ${logType})`);
- }
- };
- class Logger {
- /**
- * Gives you an instance of a Logger to capture messages according to
- * Firebase's logging scheme.
- *
- * @param name The name that the logs will be associated with
- */
- constructor(name) {
- this.name = name;
- /**
- * The log level of the given Logger instance.
- */
- this._logLevel = defaultLogLevel;
- /**
- * The main (internal) log handler for the Logger instance.
- * Can be set to a new function in internal package code but not by user.
- */
- this._logHandler = defaultLogHandler;
- /**
- * The optional, additional, user-defined log handler for the Logger instance.
- */
- this._userLogHandler = null;
- /**
- * Capture the current instance for later use
- */
- instances.push(this);
- }
- get logLevel() {
- return this._logLevel;
- }
- set logLevel(val) {
- if (!(val in LogLevel)) {
- throw new TypeError(`Invalid value "${val}" assigned to \`logLevel\``);
- }
- this._logLevel = val;
- }
- // Workaround for setter/getter having to be the same type.
- setLogLevel(val) {
- this._logLevel = typeof val === 'string' ? levelStringToEnum[val] : val;
- }
- get logHandler() {
- return this._logHandler;
- }
- set logHandler(val) {
- if (typeof val !== 'function') {
- throw new TypeError('Value assigned to `logHandler` must be a function');
- }
- this._logHandler = val;
- }
- get userLogHandler() {
- return this._userLogHandler;
- }
- set userLogHandler(val) {
- this._userLogHandler = val;
- }
- /**
- * The functions below are all based on the `console` interface
- */
- debug(...args) {
- this._userLogHandler && this._userLogHandler(this, LogLevel.DEBUG, ...args);
- this._logHandler(this, LogLevel.DEBUG, ...args);
- }
- log(...args) {
- this._userLogHandler &&
- this._userLogHandler(this, LogLevel.VERBOSE, ...args);
- this._logHandler(this, LogLevel.VERBOSE, ...args);
- }
- info(...args) {
- this._userLogHandler && this._userLogHandler(this, LogLevel.INFO, ...args);
- this._logHandler(this, LogLevel.INFO, ...args);
- }
- warn(...args) {
- this._userLogHandler && this._userLogHandler(this, LogLevel.WARN, ...args);
- this._logHandler(this, LogLevel.WARN, ...args);
- }
- error(...args) {
- this._userLogHandler && this._userLogHandler(this, LogLevel.ERROR, ...args);
- this._logHandler(this, LogLevel.ERROR, ...args);
- }
- }
- function setLogLevel$2(level) {
- instances.forEach(inst => {
- inst.setLogLevel(level);
- });
- }
- function setUserLogHandler(logCallback, options) {
- for (const instance of instances) {
- let customLogLevel = null;
- if (options && options.level) {
- customLogLevel = levelStringToEnum[options.level];
- }
- if (logCallback === null) {
- instance.userLogHandler = null;
- }
- else {
- instance.userLogHandler = (instance, level, ...args) => {
- const message = args
- .map(arg => {
- if (arg == null) {
- return null;
- }
- else if (typeof arg === 'string') {
- return arg;
- }
- else if (typeof arg === 'number' || typeof arg === 'boolean') {
- return arg.toString();
- }
- else if (arg instanceof Error) {
- return arg.message;
- }
- else {
- try {
- return JSON.stringify(arg);
- }
- catch (ignored) {
- return null;
- }
- }
- })
- .filter(arg => arg)
- .join(' ');
- if (level >= (customLogLevel !== null && customLogLevel !== void 0 ? customLogLevel : instance.logLevel)) {
- logCallback({
- level: LogLevel[level].toLowerCase(),
- message,
- args,
- type: instance.name
- });
- }
- };
- }
- }
- }
-
- const instanceOfAny$1 = (object, constructors) => constructors.some((c) => object instanceof c);
-
- let idbProxyableTypes$1;
- let cursorAdvanceMethods$1;
- // This is a function to prevent it throwing up in node environments.
- function getIdbProxyableTypes$1() {
- return (idbProxyableTypes$1 ||
- (idbProxyableTypes$1 = [
- IDBDatabase,
- IDBObjectStore,
- IDBIndex,
- IDBCursor,
- IDBTransaction,
- ]));
- }
- // This is a function to prevent it throwing up in node environments.
- function getCursorAdvanceMethods$1() {
- return (cursorAdvanceMethods$1 ||
- (cursorAdvanceMethods$1 = [
- IDBCursor.prototype.advance,
- IDBCursor.prototype.continue,
- IDBCursor.prototype.continuePrimaryKey,
- ]));
- }
- const cursorRequestMap$1 = new WeakMap();
- const transactionDoneMap$1 = new WeakMap();
- const transactionStoreNamesMap$1 = new WeakMap();
- const transformCache$1 = new WeakMap();
- const reverseTransformCache$1 = new WeakMap();
- function promisifyRequest$1(request) {
- const promise = new Promise((resolve, reject) => {
- const unlisten = () => {
- request.removeEventListener('success', success);
- request.removeEventListener('error', error);
- };
- const success = () => {
- resolve(wrap$1(request.result));
- unlisten();
- };
- const error = () => {
- reject(request.error);
- unlisten();
- };
- request.addEventListener('success', success);
- request.addEventListener('error', error);
- });
- promise
- .then((value) => {
- // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
- // (see wrapFunction).
- if (value instanceof IDBCursor) {
- cursorRequestMap$1.set(value, request);
- }
- // Catching to avoid "Uncaught Promise exceptions"
- })
- .catch(() => { });
- // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
- // is because we create many promises from a single IDBRequest.
- reverseTransformCache$1.set(promise, request);
- return promise;
- }
- function cacheDonePromiseForTransaction$1(tx) {
- // Early bail if we've already created a done promise for this transaction.
- if (transactionDoneMap$1.has(tx))
- return;
- const done = new Promise((resolve, reject) => {
- const unlisten = () => {
- tx.removeEventListener('complete', complete);
- tx.removeEventListener('error', error);
- tx.removeEventListener('abort', error);
- };
- const complete = () => {
- resolve();
- unlisten();
- };
- const error = () => {
- reject(tx.error || new DOMException('AbortError', 'AbortError'));
- unlisten();
- };
- tx.addEventListener('complete', complete);
- tx.addEventListener('error', error);
- tx.addEventListener('abort', error);
- });
- // Cache it for later retrieval.
- transactionDoneMap$1.set(tx, done);
- }
- let idbProxyTraps$1 = {
- get(target, prop, receiver) {
- if (target instanceof IDBTransaction) {
- // Special handling for transaction.done.
- if (prop === 'done')
- return transactionDoneMap$1.get(target);
- // Polyfill for objectStoreNames because of Edge.
- if (prop === 'objectStoreNames') {
- return target.objectStoreNames || transactionStoreNamesMap$1.get(target);
- }
- // Make tx.store return the only store in the transaction, or undefined if there are many.
- if (prop === 'store') {
- return receiver.objectStoreNames[1]
- ? undefined
- : receiver.objectStore(receiver.objectStoreNames[0]);
- }
- }
- // Else transform whatever we get back.
- return wrap$1(target[prop]);
- },
- set(target, prop, value) {
- target[prop] = value;
- return true;
- },
- has(target, prop) {
- if (target instanceof IDBTransaction &&
- (prop === 'done' || prop === 'store')) {
- return true;
- }
- return prop in target;
- },
- };
- function replaceTraps$1(callback) {
- idbProxyTraps$1 = callback(idbProxyTraps$1);
- }
- function wrapFunction$1(func) {
- // Due to expected object equality (which is enforced by the caching in `wrap`), we
- // only create one new func per func.
- // Edge doesn't support objectStoreNames (booo), so we polyfill it here.
- if (func === IDBDatabase.prototype.transaction &&
- !('objectStoreNames' in IDBTransaction.prototype)) {
- return function (storeNames, ...args) {
- const tx = func.call(unwrap$2(this), storeNames, ...args);
- transactionStoreNamesMap$1.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
- return wrap$1(tx);
- };
- }
- // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
- // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
- // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
- // with real promises, so each advance methods returns a new promise for the cursor object, or
- // undefined if the end of the cursor has been reached.
- if (getCursorAdvanceMethods$1().includes(func)) {
- return function (...args) {
- // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
- // the original object.
- func.apply(unwrap$2(this), args);
- return wrap$1(cursorRequestMap$1.get(this));
- };
- }
- return function (...args) {
- // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
- // the original object.
- return wrap$1(func.apply(unwrap$2(this), args));
- };
- }
- function transformCachableValue$1(value) {
- if (typeof value === 'function')
- return wrapFunction$1(value);
- // This doesn't return, it just creates a 'done' promise for the transaction,
- // which is later returned for transaction.done (see idbObjectHandler).
- if (value instanceof IDBTransaction)
- cacheDonePromiseForTransaction$1(value);
- if (instanceOfAny$1(value, getIdbProxyableTypes$1()))
- return new Proxy(value, idbProxyTraps$1);
- // Return the same value back if we're not going to transform it.
- return value;
- }
- function wrap$1(value) {
- // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
- // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
- if (value instanceof IDBRequest)
- return promisifyRequest$1(value);
- // If we've already transformed this value before, reuse the transformed value.
- // This is faster, but it also provides object equality.
- if (transformCache$1.has(value))
- return transformCache$1.get(value);
- const newValue = transformCachableValue$1(value);
- // Not all types are transformed.
- // These may be primitive types, so they can't be WeakMap keys.
- if (newValue !== value) {
- transformCache$1.set(value, newValue);
- reverseTransformCache$1.set(newValue, value);
- }
- return newValue;
- }
- const unwrap$2 = (value) => reverseTransformCache$1.get(value);
-
- /**
- * Open a database.
- *
- * @param name Name of the database.
- * @param version Schema version.
- * @param callbacks Additional callbacks.
- */
- function openDB$1(name, version, { blocked, upgrade, blocking, terminated } = {}) {
- const request = indexedDB.open(name, version);
- const openPromise = wrap$1(request);
- if (upgrade) {
- request.addEventListener('upgradeneeded', (event) => {
- upgrade(wrap$1(request.result), event.oldVersion, event.newVersion, wrap$1(request.transaction), event);
- });
- }
- if (blocked) {
- request.addEventListener('blocked', (event) => blocked(
- // Casting due to https://github.com/microsoft/TypeScript-DOM-lib-generator/pull/1405
- event.oldVersion, event.newVersion, event));
- }
- openPromise
- .then((db) => {
- if (terminated)
- db.addEventListener('close', () => terminated());
- if (blocking) {
- db.addEventListener('versionchange', (event) => blocking(event.oldVersion, event.newVersion, event));
- }
- })
- .catch(() => { });
- return openPromise;
- }
-
- const readMethods$1 = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
- const writeMethods$1 = ['put', 'add', 'delete', 'clear'];
- const cachedMethods$1 = new Map();
- function getMethod$1(target, prop) {
- if (!(target instanceof IDBDatabase &&
- !(prop in target) &&
- typeof prop === 'string')) {
- return;
- }
- if (cachedMethods$1.get(prop))
- return cachedMethods$1.get(prop);
- const targetFuncName = prop.replace(/FromIndex$/, '');
- const useIndex = prop !== targetFuncName;
- const isWrite = writeMethods$1.includes(targetFuncName);
- if (
- // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
- !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||
- !(isWrite || readMethods$1.includes(targetFuncName))) {
- return;
- }
- const method = async function (storeName, ...args) {
- // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
- const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
- let target = tx.store;
- if (useIndex)
- target = target.index(args.shift());
- // Must reject if op rejects.
- // If it's a write operation, must reject if tx.done rejects.
- // Must reject with op rejection first.
- // Must resolve with op value.
- // Must handle both promises (no unhandled rejections)
- return (await Promise.all([
- target[targetFuncName](...args),
- isWrite && tx.done,
- ]))[0];
- };
- cachedMethods$1.set(prop, method);
- return method;
- }
- replaceTraps$1((oldTraps) => ({
- ...oldTraps,
- get: (target, prop, receiver) => getMethod$1(target, prop) || oldTraps.get(target, prop, receiver),
- has: (target, prop) => !!getMethod$1(target, prop) || oldTraps.has(target, prop),
- }));
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class PlatformLoggerServiceImpl {
- constructor(container) {
- this.container = container;
- }
- // In initial implementation, this will be called by installations on
- // auth token refresh, and installations will send this string.
- getPlatformInfoString() {
- const providers = this.container.getProviders();
- // Loop through providers and get library/version pairs from any that are
- // version components.
- return providers
- .map(provider => {
- if (isVersionServiceProvider(provider)) {
- const service = provider.getImmediate();
- return `${service.library}/${service.version}`;
- }
- else {
- return null;
- }
- })
- .filter(logString => logString)
- .join(' ');
- }
- }
- /**
- *
- * @param provider check if this provider provides a VersionService
- *
- * NOTE: Using Provider<'app-version'> is a hack to indicate that the provider
- * provides VersionService. The provider is not necessarily a 'app-version'
- * provider.
- */
- function isVersionServiceProvider(provider) {
- const component = provider.getComponent();
- return (component === null || component === void 0 ? void 0 : component.type) === "VERSION" /* ComponentType.VERSION */;
- }
-
- const name$o = "@firebase/app";
- const version$1$1 = "0.9.11";
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const logger$2 = new Logger('@firebase/app');
-
- const name$n = "@firebase/app-compat";
-
- const name$m = "@firebase/analytics-compat";
-
- const name$l = "@firebase/analytics";
-
- const name$k = "@firebase/app-check-compat";
-
- const name$j = "@firebase/app-check";
-
- const name$i = "@firebase/auth";
-
- const name$h = "@firebase/auth-compat";
-
- const name$g = "@firebase/database";
-
- const name$f = "@firebase/database-compat";
-
- const name$e = "@firebase/functions";
-
- const name$d = "@firebase/functions-compat";
-
- const name$c = "@firebase/installations";
-
- const name$b = "@firebase/installations-compat";
-
- const name$a = "@firebase/messaging";
-
- const name$9 = "@firebase/messaging-compat";
-
- const name$8 = "@firebase/performance";
-
- const name$7$1 = "@firebase/performance-compat";
-
- const name$6$1 = "@firebase/remote-config";
-
- const name$5$1 = "@firebase/remote-config-compat";
-
- const name$4$1 = "@firebase/storage";
-
- const name$3$1 = "@firebase/storage-compat";
-
- const name$2$1 = "@firebase/firestore";
-
- const name$1$1 = "@firebase/firestore-compat";
-
- const name$p = "firebase";
- const version$8 = "9.22.1";
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * The default app name
- *
- * @internal
- */
- const DEFAULT_ENTRY_NAME$1 = '[DEFAULT]';
- const PLATFORM_LOG_STRING = {
- [name$o]: 'fire-core',
- [name$n]: 'fire-core-compat',
- [name$l]: 'fire-analytics',
- [name$m]: 'fire-analytics-compat',
- [name$j]: 'fire-app-check',
- [name$k]: 'fire-app-check-compat',
- [name$i]: 'fire-auth',
- [name$h]: 'fire-auth-compat',
- [name$g]: 'fire-rtdb',
- [name$f]: 'fire-rtdb-compat',
- [name$e]: 'fire-fn',
- [name$d]: 'fire-fn-compat',
- [name$c]: 'fire-iid',
- [name$b]: 'fire-iid-compat',
- [name$a]: 'fire-fcm',
- [name$9]: 'fire-fcm-compat',
- [name$8]: 'fire-perf',
- [name$7$1]: 'fire-perf-compat',
- [name$6$1]: 'fire-rc',
- [name$5$1]: 'fire-rc-compat',
- [name$4$1]: 'fire-gcs',
- [name$3$1]: 'fire-gcs-compat',
- [name$2$1]: 'fire-fst',
- [name$1$1]: 'fire-fst-compat',
- 'fire-js': 'fire-js',
- [name$p]: 'fire-js-all'
- };
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * @internal
- */
- const _apps = new Map();
- /**
- * Registered components.
- *
- * @internal
- */
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const _components = new Map();
- /**
- * @param component - the component being added to this app's container
- *
- * @internal
- */
- function _addComponent(app, component) {
- try {
- app.container.addComponent(component);
- }
- catch (e) {
- logger$2.debug(`Component ${component.name} failed to register with FirebaseApp ${app.name}`, e);
- }
- }
- /**
- *
- * @internal
- */
- function _addOrOverwriteComponent(app, component) {
- app.container.addOrOverwriteComponent(component);
- }
- /**
- *
- * @param component - the component to register
- * @returns whether or not the component is registered successfully
- *
- * @internal
- */
- function _registerComponent(component) {
- const componentName = component.name;
- if (_components.has(componentName)) {
- logger$2.debug(`There were multiple attempts to register component ${componentName}.`);
- return false;
- }
- _components.set(componentName, component);
- // add the component to existing app instances
- for (const app of _apps.values()) {
- _addComponent(app, component);
- }
- return true;
- }
- /**
- *
- * @param app - FirebaseApp instance
- * @param name - service name
- *
- * @returns the provider for the service with the matching name
- *
- * @internal
- */
- function _getProvider(app, name) {
- const heartbeatController = app.container
- .getProvider('heartbeat')
- .getImmediate({ optional: true });
- if (heartbeatController) {
- void heartbeatController.triggerHeartbeat();
- }
- return app.container.getProvider(name);
- }
- /**
- *
- * @param app - FirebaseApp instance
- * @param name - service name
- * @param instanceIdentifier - service instance identifier in case the service supports multiple instances
- *
- * @internal
- */
- function _removeServiceInstance(app, name, instanceIdentifier = DEFAULT_ENTRY_NAME$1) {
- _getProvider(app, name).clearInstance(instanceIdentifier);
- }
- /**
- * Test only
- *
- * @internal
- */
- function _clearComponents() {
- _components.clear();
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const ERRORS$1 = {
- ["no-app" /* AppError.NO_APP */]: "No Firebase App '{$appName}' has been created - " +
- 'call initializeApp() first',
- ["bad-app-name" /* AppError.BAD_APP_NAME */]: "Illegal App name: '{$appName}",
- ["duplicate-app" /* AppError.DUPLICATE_APP */]: "Firebase App named '{$appName}' already exists with different options or config",
- ["app-deleted" /* AppError.APP_DELETED */]: "Firebase App named '{$appName}' already deleted",
- ["no-options" /* AppError.NO_OPTIONS */]: 'Need to provide options, when not being deployed to hosting via source.',
- ["invalid-app-argument" /* AppError.INVALID_APP_ARGUMENT */]: 'firebase.{$appName}() takes either no argument or a ' +
- 'Firebase App instance.',
- ["invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */]: 'First argument to `onLog` must be null or a function.',
- ["idb-open" /* AppError.IDB_OPEN */]: 'Error thrown when opening IndexedDB. Original error: {$originalErrorMessage}.',
- ["idb-get" /* AppError.IDB_GET */]: 'Error thrown when reading from IndexedDB. Original error: {$originalErrorMessage}.',
- ["idb-set" /* AppError.IDB_WRITE */]: 'Error thrown when writing to IndexedDB. Original error: {$originalErrorMessage}.',
- ["idb-delete" /* AppError.IDB_DELETE */]: 'Error thrown when deleting from IndexedDB. Original error: {$originalErrorMessage}.'
- };
- const ERROR_FACTORY$3 = new ErrorFactory('app', 'Firebase', ERRORS$1);
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class FirebaseAppImpl$1 {
- constructor(options, config, container) {
- this._isDeleted = false;
- this._options = Object.assign({}, options);
- this._config = Object.assign({}, config);
- this._name = config.name;
- this._automaticDataCollectionEnabled =
- config.automaticDataCollectionEnabled;
- this._container = container;
- this.container.addComponent(new Component('app', () => this, "PUBLIC" /* ComponentType.PUBLIC */));
- }
- get automaticDataCollectionEnabled() {
- this.checkDestroyed();
- return this._automaticDataCollectionEnabled;
- }
- set automaticDataCollectionEnabled(val) {
- this.checkDestroyed();
- this._automaticDataCollectionEnabled = val;
- }
- get name() {
- this.checkDestroyed();
- return this._name;
- }
- get options() {
- this.checkDestroyed();
- return this._options;
- }
- get config() {
- this.checkDestroyed();
- return this._config;
- }
- get container() {
- return this._container;
- }
- get isDeleted() {
- return this._isDeleted;
- }
- set isDeleted(val) {
- this._isDeleted = val;
- }
- /**
- * This function will throw an Error if the App has already been deleted -
- * use before performing API actions on the App.
- */
- checkDestroyed() {
- if (this.isDeleted) {
- throw ERROR_FACTORY$3.create("app-deleted" /* AppError.APP_DELETED */, { appName: this._name });
- }
- }
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * The current SDK version.
- *
- * @public
- */
- const SDK_VERSION$1 = version$8;
- function initializeApp(_options, rawConfig = {}) {
- let options = _options;
- if (typeof rawConfig !== 'object') {
- const name = rawConfig;
- rawConfig = { name };
- }
- const config = Object.assign({ name: DEFAULT_ENTRY_NAME$1, automaticDataCollectionEnabled: false }, rawConfig);
- const name = config.name;
- if (typeof name !== 'string' || !name) {
- throw ERROR_FACTORY$3.create("bad-app-name" /* AppError.BAD_APP_NAME */, {
- appName: String(name)
- });
- }
- options || (options = getDefaultAppConfig());
- if (!options) {
- throw ERROR_FACTORY$3.create("no-options" /* AppError.NO_OPTIONS */);
- }
- const existingApp = _apps.get(name);
- if (existingApp) {
- // return the existing app if options and config deep equal the ones in the existing app.
- if (deepEqual(options, existingApp.options) &&
- deepEqual(config, existingApp.config)) {
- return existingApp;
- }
- else {
- throw ERROR_FACTORY$3.create("duplicate-app" /* AppError.DUPLICATE_APP */, { appName: name });
- }
- }
- const container = new ComponentContainer(name);
- for (const component of _components.values()) {
- container.addComponent(component);
- }
- const newApp = new FirebaseAppImpl$1(options, config, container);
- _apps.set(name, newApp);
- return newApp;
- }
- /**
- * Retrieves a {@link @firebase/app#FirebaseApp} instance.
- *
- * When called with no arguments, the default app is returned. When an app name
- * is provided, the app corresponding to that name is returned.
- *
- * An exception is thrown if the app being retrieved has not yet been
- * initialized.
- *
- * @example
- * ```javascript
- * // Return the default app
- * const app = getApp();
- * ```
- *
- * @example
- * ```javascript
- * // Return a named app
- * const otherApp = getApp("otherApp");
- * ```
- *
- * @param name - Optional name of the app to return. If no name is
- * provided, the default is `"[DEFAULT]"`.
- *
- * @returns The app corresponding to the provided app name.
- * If no app name is provided, the default app is returned.
- *
- * @public
- */
- function getApp(name = DEFAULT_ENTRY_NAME$1) {
- const app = _apps.get(name);
- if (!app && name === DEFAULT_ENTRY_NAME$1 && getDefaultAppConfig()) {
- return initializeApp();
- }
- if (!app) {
- throw ERROR_FACTORY$3.create("no-app" /* AppError.NO_APP */, { appName: name });
- }
- return app;
- }
- /**
- * A (read-only) array of all initialized apps.
- * @public
- */
- function getApps() {
- return Array.from(_apps.values());
- }
- /**
- * Renders this app unusable and frees the resources of all associated
- * services.
- *
- * @example
- * ```javascript
- * deleteApp(app)
- * .then(function() {
- * console.log("App deleted successfully");
- * })
- * .catch(function(error) {
- * console.log("Error deleting app:", error);
- * });
- * ```
- *
- * @public
- */
- async function deleteApp(app) {
- const name = app.name;
- if (_apps.has(name)) {
- _apps.delete(name);
- await Promise.all(app.container
- .getProviders()
- .map(provider => provider.delete()));
- app.isDeleted = true;
- }
- }
- /**
- * Registers a library's name and version for platform logging purposes.
- * @param library - Name of 1p or 3p library (e.g. firestore, angularfire)
- * @param version - Current version of that library.
- * @param variant - Bundle variant, e.g., node, rn, etc.
- *
- * @public
- */
- function registerVersion(libraryKeyOrName, version, variant) {
- var _a;
- // TODO: We can use this check to whitelist strings when/if we set up
- // a good whitelist system.
- let library = (_a = PLATFORM_LOG_STRING[libraryKeyOrName]) !== null && _a !== void 0 ? _a : libraryKeyOrName;
- if (variant) {
- library += `-${variant}`;
- }
- const libraryMismatch = library.match(/\s|\//);
- const versionMismatch = version.match(/\s|\//);
- if (libraryMismatch || versionMismatch) {
- const warning = [
- `Unable to register library "${library}" with version "${version}":`
- ];
- if (libraryMismatch) {
- warning.push(`library name "${library}" contains illegal characters (whitespace or "/")`);
- }
- if (libraryMismatch && versionMismatch) {
- warning.push('and');
- }
- if (versionMismatch) {
- warning.push(`version name "${version}" contains illegal characters (whitespace or "/")`);
- }
- logger$2.warn(warning.join(' '));
- return;
- }
- _registerComponent(new Component(`${library}-version`, () => ({ library, version }), "VERSION" /* ComponentType.VERSION */));
- }
- /**
- * Sets log handler for all Firebase SDKs.
- * @param logCallback - An optional custom log handler that executes user code whenever
- * the Firebase SDK makes a logging call.
- *
- * @public
- */
- function onLog(logCallback, options) {
- if (logCallback !== null && typeof logCallback !== 'function') {
- throw ERROR_FACTORY$3.create("invalid-log-argument" /* AppError.INVALID_LOG_ARGUMENT */);
- }
- setUserLogHandler(logCallback, options);
- }
- /**
- * Sets log level for all Firebase SDKs.
- *
- * All of the log types above the current log level are captured (i.e. if
- * you set the log level to `info`, errors are logged, but `debug` and
- * `verbose` logs are not).
- *
- * @public
- */
- function setLogLevel$1(logLevel) {
- setLogLevel$2(logLevel);
- }
-
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const DB_NAME$1 = 'firebase-heartbeat-database';
- const DB_VERSION$1 = 1;
- const STORE_NAME = 'firebase-heartbeat-store';
- let dbPromise$1 = null;
- function getDbPromise$1() {
- if (!dbPromise$1) {
- dbPromise$1 = openDB$1(DB_NAME$1, DB_VERSION$1, {
- upgrade: (db, oldVersion) => {
- // We don't use 'break' in this switch statement, the fall-through
- // behavior is what we want, because if there are multiple versions between
- // the old version and the current version, we want ALL the migrations
- // that correspond to those versions to run, not only the last one.
- // eslint-disable-next-line default-case
- switch (oldVersion) {
- case 0:
- db.createObjectStore(STORE_NAME);
- }
- }
- }).catch(e => {
- throw ERROR_FACTORY$3.create("idb-open" /* AppError.IDB_OPEN */, {
- originalErrorMessage: e.message
- });
- });
- }
- return dbPromise$1;
- }
- async function readHeartbeatsFromIndexedDB(app) {
- try {
- const db = await getDbPromise$1();
- const result = await db
- .transaction(STORE_NAME)
- .objectStore(STORE_NAME)
- .get(computeKey(app));
- return result;
- }
- catch (e) {
- if (e instanceof FirebaseError) {
- logger$2.warn(e.message);
- }
- else {
- const idbGetError = ERROR_FACTORY$3.create("idb-get" /* AppError.IDB_GET */, {
- originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
- });
- logger$2.warn(idbGetError.message);
- }
- }
- }
- async function writeHeartbeatsToIndexedDB(app, heartbeatObject) {
- try {
- const db = await getDbPromise$1();
- const tx = db.transaction(STORE_NAME, 'readwrite');
- const objectStore = tx.objectStore(STORE_NAME);
- await objectStore.put(heartbeatObject, computeKey(app));
- await tx.done;
- }
- catch (e) {
- if (e instanceof FirebaseError) {
- logger$2.warn(e.message);
- }
- else {
- const idbGetError = ERROR_FACTORY$3.create("idb-set" /* AppError.IDB_WRITE */, {
- originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
- });
- logger$2.warn(idbGetError.message);
- }
- }
- }
- function computeKey(app) {
- return `${app.name}!${app.options.appId}`;
- }
-
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const MAX_HEADER_BYTES = 1024;
- // 30 days
- const STORED_HEARTBEAT_RETENTION_MAX_MILLIS = 30 * 24 * 60 * 60 * 1000;
- class HeartbeatServiceImpl {
- constructor(container) {
- this.container = container;
- /**
- * In-memory cache for heartbeats, used by getHeartbeatsHeader() to generate
- * the header string.
- * Stores one record per date. This will be consolidated into the standard
- * format of one record per user agent string before being sent as a header.
- * Populated from indexedDB when the controller is instantiated and should
- * be kept in sync with indexedDB.
- * Leave public for easier testing.
- */
- this._heartbeatsCache = null;
- const app = this.container.getProvider('app').getImmediate();
- this._storage = new HeartbeatStorageImpl(app);
- this._heartbeatsCachePromise = this._storage.read().then(result => {
- this._heartbeatsCache = result;
- return result;
- });
- }
- /**
- * Called to report a heartbeat. The function will generate
- * a HeartbeatsByUserAgent object, update heartbeatsCache, and persist it
- * to IndexedDB.
- * Note that we only store one heartbeat per day. So if a heartbeat for today is
- * already logged, subsequent calls to this function in the same day will be ignored.
- */
- async triggerHeartbeat() {
- const platformLogger = this.container
- .getProvider('platform-logger')
- .getImmediate();
- // This is the "Firebase user agent" string from the platform logger
- // service, not the browser user agent.
- const agent = platformLogger.getPlatformInfoString();
- const date = getUTCDateString();
- if (this._heartbeatsCache === null) {
- this._heartbeatsCache = await this._heartbeatsCachePromise;
- }
- // Do not store a heartbeat if one is already stored for this day
- // or if a header has already been sent today.
- if (this._heartbeatsCache.lastSentHeartbeatDate === date ||
- this._heartbeatsCache.heartbeats.some(singleDateHeartbeat => singleDateHeartbeat.date === date)) {
- return;
- }
- else {
- // There is no entry for this date. Create one.
- this._heartbeatsCache.heartbeats.push({ date, agent });
- }
- // Remove entries older than 30 days.
- this._heartbeatsCache.heartbeats = this._heartbeatsCache.heartbeats.filter(singleDateHeartbeat => {
- const hbTimestamp = new Date(singleDateHeartbeat.date).valueOf();
- const now = Date.now();
- return now - hbTimestamp <= STORED_HEARTBEAT_RETENTION_MAX_MILLIS;
- });
- return this._storage.overwrite(this._heartbeatsCache);
- }
- /**
- * Returns a base64 encoded string which can be attached to the heartbeat-specific header directly.
- * It also clears all heartbeats from memory as well as in IndexedDB.
- *
- * NOTE: Consuming product SDKs should not send the header if this method
- * returns an empty string.
- */
- async getHeartbeatsHeader() {
- if (this._heartbeatsCache === null) {
- await this._heartbeatsCachePromise;
- }
- // If it's still null or the array is empty, there is no data to send.
- if (this._heartbeatsCache === null ||
- this._heartbeatsCache.heartbeats.length === 0) {
- return '';
- }
- const date = getUTCDateString();
- // Extract as many heartbeats from the cache as will fit under the size limit.
- const { heartbeatsToSend, unsentEntries } = extractHeartbeatsForHeader(this._heartbeatsCache.heartbeats);
- const headerString = base64urlEncodeWithoutPadding(JSON.stringify({ version: 2, heartbeats: heartbeatsToSend }));
- // Store last sent date to prevent another being logged/sent for the same day.
- this._heartbeatsCache.lastSentHeartbeatDate = date;
- if (unsentEntries.length > 0) {
- // Store any unsent entries if they exist.
- this._heartbeatsCache.heartbeats = unsentEntries;
- // This seems more likely than emptying the array (below) to lead to some odd state
- // since the cache isn't empty and this will be called again on the next request,
- // and is probably safest if we await it.
- await this._storage.overwrite(this._heartbeatsCache);
- }
- else {
- this._heartbeatsCache.heartbeats = [];
- // Do not wait for this, to reduce latency.
- void this._storage.overwrite(this._heartbeatsCache);
- }
- return headerString;
- }
- }
- function getUTCDateString() {
- const today = new Date();
- // Returns date format 'YYYY-MM-DD'
- return today.toISOString().substring(0, 10);
- }
- function extractHeartbeatsForHeader(heartbeatsCache, maxSize = MAX_HEADER_BYTES) {
- // Heartbeats grouped by user agent in the standard format to be sent in
- // the header.
- const heartbeatsToSend = [];
- // Single date format heartbeats that are not sent.
- let unsentEntries = heartbeatsCache.slice();
- for (const singleDateHeartbeat of heartbeatsCache) {
- // Look for an existing entry with the same user agent.
- const heartbeatEntry = heartbeatsToSend.find(hb => hb.agent === singleDateHeartbeat.agent);
- if (!heartbeatEntry) {
- // If no entry for this user agent exists, create one.
- heartbeatsToSend.push({
- agent: singleDateHeartbeat.agent,
- dates: [singleDateHeartbeat.date]
- });
- if (countBytes(heartbeatsToSend) > maxSize) {
- // If the header would exceed max size, remove the added heartbeat
- // entry and stop adding to the header.
- heartbeatsToSend.pop();
- break;
- }
- }
- else {
- heartbeatEntry.dates.push(singleDateHeartbeat.date);
- // If the header would exceed max size, remove the added date
- // and stop adding to the header.
- if (countBytes(heartbeatsToSend) > maxSize) {
- heartbeatEntry.dates.pop();
- break;
- }
- }
- // Pop unsent entry from queue. (Skipped if adding the entry exceeded
- // quota and the loop breaks early.)
- unsentEntries = unsentEntries.slice(1);
- }
- return {
- heartbeatsToSend,
- unsentEntries
- };
- }
- class HeartbeatStorageImpl {
- constructor(app) {
- this.app = app;
- this._canUseIndexedDBPromise = this.runIndexedDBEnvironmentCheck();
- }
- async runIndexedDBEnvironmentCheck() {
- if (!isIndexedDBAvailable()) {
- return false;
- }
- else {
- return validateIndexedDBOpenable()
- .then(() => true)
- .catch(() => false);
- }
- }
- /**
- * Read all heartbeats.
- */
- async read() {
- const canUseIndexedDB = await this._canUseIndexedDBPromise;
- if (!canUseIndexedDB) {
- return { heartbeats: [] };
- }
- else {
- const idbHeartbeatObject = await readHeartbeatsFromIndexedDB(this.app);
- return idbHeartbeatObject || { heartbeats: [] };
- }
- }
- // overwrite the storage with the provided heartbeats
- async overwrite(heartbeatsObject) {
- var _a;
- const canUseIndexedDB = await this._canUseIndexedDBPromise;
- if (!canUseIndexedDB) {
- return;
- }
- else {
- const existingHeartbeatsObject = await this.read();
- return writeHeartbeatsToIndexedDB(this.app, {
- lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
- heartbeats: heartbeatsObject.heartbeats
- });
- }
- }
- // add heartbeats
- async add(heartbeatsObject) {
- var _a;
- const canUseIndexedDB = await this._canUseIndexedDBPromise;
- if (!canUseIndexedDB) {
- return;
- }
- else {
- const existingHeartbeatsObject = await this.read();
- return writeHeartbeatsToIndexedDB(this.app, {
- lastSentHeartbeatDate: (_a = heartbeatsObject.lastSentHeartbeatDate) !== null && _a !== void 0 ? _a : existingHeartbeatsObject.lastSentHeartbeatDate,
- heartbeats: [
- ...existingHeartbeatsObject.heartbeats,
- ...heartbeatsObject.heartbeats
- ]
- });
- }
- }
- }
- /**
- * Calculate bytes of a HeartbeatsByUserAgent array after being wrapped
- * in a platform logging header JSON object, stringified, and converted
- * to base 64.
- */
- function countBytes(heartbeatsCache) {
- // base64 has a restricted set of characters, all of which should be 1 byte.
- return base64urlEncodeWithoutPadding(
- // heartbeatsCache wrapper properties
- JSON.stringify({ version: 2, heartbeats: heartbeatsCache })).length;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function registerCoreComponents$1(variant) {
- _registerComponent(new Component('platform-logger', container => new PlatformLoggerServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
- _registerComponent(new Component('heartbeat', container => new HeartbeatServiceImpl(container), "PRIVATE" /* ComponentType.PRIVATE */));
- // Register `app` package.
- registerVersion(name$o, version$1$1, variant);
- // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
- registerVersion(name$o, version$1$1, 'esm2017');
- // Register platform SDK identifier (no version).
- registerVersion('fire-js', '');
- }
-
- /**
- * Firebase App
- *
- * @remarks This package coordinates the communication between the different Firebase components
- * @packageDocumentation
- */
- registerCoreComponents$1('');
-
- var modularAPIs = /*#__PURE__*/Object.freeze({
- __proto__: null,
- SDK_VERSION: SDK_VERSION$1,
- _DEFAULT_ENTRY_NAME: DEFAULT_ENTRY_NAME$1,
- _addComponent: _addComponent,
- _addOrOverwriteComponent: _addOrOverwriteComponent,
- _apps: _apps,
- _clearComponents: _clearComponents,
- _components: _components,
- _getProvider: _getProvider,
- _registerComponent: _registerComponent,
- _removeServiceInstance: _removeServiceInstance,
- deleteApp: deleteApp,
- getApp: getApp,
- getApps: getApps,
- initializeApp: initializeApp,
- onLog: onLog,
- registerVersion: registerVersion,
- setLogLevel: setLogLevel$1,
- FirebaseError: FirebaseError
- });
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Global context object for a collection of services using
- * a shared authentication state.
- *
- * marked as internal because it references internal types exported from @firebase/app
- * @internal
- */
- class FirebaseAppImpl {
- constructor(_delegate, firebase) {
- this._delegate = _delegate;
- this.firebase = firebase;
- // add itself to container
- _addComponent(_delegate, new Component('app-compat', () => this, "PUBLIC" /* ComponentType.PUBLIC */));
- this.container = _delegate.container;
- }
- get automaticDataCollectionEnabled() {
- return this._delegate.automaticDataCollectionEnabled;
- }
- set automaticDataCollectionEnabled(val) {
- this._delegate.automaticDataCollectionEnabled = val;
- }
- get name() {
- return this._delegate.name;
- }
- get options() {
- return this._delegate.options;
- }
- delete() {
- return new Promise(resolve => {
- this._delegate.checkDestroyed();
- resolve();
- }).then(() => {
- this.firebase.INTERNAL.removeApp(this.name);
- return deleteApp(this._delegate);
- });
- }
- /**
- * Return a service instance associated with this app (creating it
- * on demand), identified by the passed instanceIdentifier.
- *
- * NOTE: Currently storage and functions are the only ones that are leveraging this
- * functionality. They invoke it by calling:
- *
- * ```javascript
- * firebase.app().storage('STORAGE BUCKET ID')
- * ```
- *
- * The service name is passed to this already
- * @internal
- */
- _getService(name, instanceIdentifier = DEFAULT_ENTRY_NAME$1) {
- var _a;
- this._delegate.checkDestroyed();
- // Initialize instance if InstatiationMode is `EXPLICIT`.
- const provider = this._delegate.container.getProvider(name);
- if (!provider.isInitialized() &&
- ((_a = provider.getComponent()) === null || _a === void 0 ? void 0 : _a.instantiationMode) === "EXPLICIT" /* InstantiationMode.EXPLICIT */) {
- provider.initialize();
- }
- // getImmediate will always succeed because _getService is only called for registered components.
- return provider.getImmediate({
- identifier: instanceIdentifier
- });
- }
- /**
- * Remove a service instance from the cache, so we will create a new instance for this service
- * when people try to get it again.
- *
- * NOTE: currently only firestore uses this functionality to support firestore shutdown.
- *
- * @param name The service name
- * @param instanceIdentifier instance identifier in case multiple instances are allowed
- * @internal
- */
- _removeServiceInstance(name, instanceIdentifier = DEFAULT_ENTRY_NAME$1) {
- this._delegate.container
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- .getProvider(name)
- .clearInstance(instanceIdentifier);
- }
- /**
- * @param component the component being added to this app's container
- * @internal
- */
- _addComponent(component) {
- _addComponent(this._delegate, component);
- }
- _addOrOverwriteComponent(component) {
- _addOrOverwriteComponent(this._delegate, component);
- }
- toJSON() {
- return {
- name: this.name,
- automaticDataCollectionEnabled: this.automaticDataCollectionEnabled,
- options: this.options
- };
- }
- }
- // TODO: investigate why the following needs to be commented out
- // Prevent dead-code elimination of these methods w/o invalid property
- // copying.
- // (FirebaseAppImpl.prototype.name && FirebaseAppImpl.prototype.options) ||
- // FirebaseAppImpl.prototype.delete ||
- // console.log('dc');
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const ERRORS = {
- ["no-app" /* AppError.NO_APP */]: "No Firebase App '{$appName}' has been created - " +
- 'call Firebase App.initializeApp()',
- ["invalid-app-argument" /* AppError.INVALID_APP_ARGUMENT */]: 'firebase.{$appName}() takes either no argument or a ' +
- 'Firebase App instance.'
- };
- const ERROR_FACTORY$2 = new ErrorFactory('app-compat', 'Firebase', ERRORS);
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Because auth can't share code with other components, we attach the utility functions
- * in an internal namespace to share code.
- * This function return a firebase namespace object without
- * any utility functions, so it can be shared between the regular firebaseNamespace and
- * the lite version.
- */
- function createFirebaseNamespaceCore(firebaseAppImpl) {
- const apps = {};
- // // eslint-disable-next-line @typescript-eslint/no-explicit-any
- // const components = new Map>();
- // A namespace is a plain JavaScript Object.
- const namespace = {
- // Hack to prevent Babel from modifying the object returned
- // as the firebase namespace.
- // @ts-ignore
- __esModule: true,
- initializeApp: initializeAppCompat,
- // @ts-ignore
- app,
- registerVersion: registerVersion,
- setLogLevel: setLogLevel$1,
- onLog: onLog,
- // @ts-ignore
- apps: null,
- SDK_VERSION: SDK_VERSION$1,
- INTERNAL: {
- registerComponent: registerComponentCompat,
- removeApp,
- useAsService,
- modularAPIs
- }
- };
- // Inject a circular default export to allow Babel users who were previously
- // using:
- //
- // import firebase from 'firebase';
- // which becomes: var firebase = require('firebase').default;
- //
- // instead of
- //
- // import * as firebase from 'firebase';
- // which becomes: var firebase = require('firebase');
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- namespace['default'] = namespace;
- // firebase.apps is a read-only getter.
- Object.defineProperty(namespace, 'apps', {
- get: getApps
- });
- /**
- * Called by App.delete() - but before any services associated with the App
- * are deleted.
- */
- function removeApp(name) {
- delete apps[name];
- }
- /**
- * Get the App object for a given name (or DEFAULT).
- */
- function app(name) {
- name = name || DEFAULT_ENTRY_NAME$1;
- if (!contains$1(apps, name)) {
- throw ERROR_FACTORY$2.create("no-app" /* AppError.NO_APP */, { appName: name });
- }
- return apps[name];
- }
- // @ts-ignore
- app['App'] = firebaseAppImpl;
- /**
- * Create a new App instance (name must be unique).
- *
- * This function is idempotent. It can be called more than once and return the same instance using the same options and config.
- */
- function initializeAppCompat(options, rawConfig = {}) {
- const app = initializeApp(options, rawConfig);
- if (contains$1(apps, app.name)) {
- return apps[app.name];
- }
- const appCompat = new firebaseAppImpl(app, namespace);
- apps[app.name] = appCompat;
- return appCompat;
- }
- /*
- * Return an array of all the non-deleted FirebaseApps.
- */
- function getApps() {
- // Make a copy so caller cannot mutate the apps list.
- return Object.keys(apps).map(name => apps[name]);
- }
- function registerComponentCompat(component) {
- const componentName = component.name;
- const componentNameWithoutCompat = componentName.replace('-compat', '');
- if (_registerComponent(component) &&
- component.type === "PUBLIC" /* ComponentType.PUBLIC */) {
- // create service namespace for public components
- // The Service namespace is an accessor function ...
- const serviceNamespace = (appArg = app()) => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- if (typeof appArg[componentNameWithoutCompat] !== 'function') {
- // Invalid argument.
- // This happens in the following case: firebase.storage('gs:/')
- throw ERROR_FACTORY$2.create("invalid-app-argument" /* AppError.INVALID_APP_ARGUMENT */, {
- appName: componentName
- });
- }
- // Forward service instance lookup to the FirebaseApp.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- return appArg[componentNameWithoutCompat]();
- };
- // ... and a container for service-level properties.
- if (component.serviceProps !== undefined) {
- deepExtend(serviceNamespace, component.serviceProps);
- }
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- namespace[componentNameWithoutCompat] = serviceNamespace;
- // Patch the FirebaseAppImpl prototype
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- firebaseAppImpl.prototype[componentNameWithoutCompat] =
- // TODO: The eslint disable can be removed and the 'ignoreRestArgs'
- // option added to the no-explicit-any rule when ESlint releases it.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- function (...args) {
- const serviceFxn = this._getService.bind(this, componentName);
- return serviceFxn.apply(this, component.multipleInstances ? args : []);
- };
- }
- return component.type === "PUBLIC" /* ComponentType.PUBLIC */
- ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
- namespace[componentNameWithoutCompat]
- : null;
- }
- // Map the requested service to a registered service name
- // (used to map auth to serverAuth service when needed).
- function useAsService(app, name) {
- if (name === 'serverAuth') {
- return null;
- }
- const useService = name;
- return useService;
- }
- return namespace;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Return a firebase namespace object.
- *
- * In production, this will be called exactly once and the result
- * assigned to the 'firebase' global. It may be called multiple times
- * in unit tests.
- */
- function createFirebaseNamespace() {
- const namespace = createFirebaseNamespaceCore(FirebaseAppImpl);
- namespace.INTERNAL = Object.assign(Object.assign({}, namespace.INTERNAL), { createFirebaseNamespace,
- extendNamespace,
- createSubscribe,
- ErrorFactory,
- deepExtend });
- /**
- * Patch the top-level firebase namespace with additional properties.
- *
- * firebase.INTERNAL.extendNamespace()
- */
- function extendNamespace(props) {
- deepExtend(namespace, props);
- }
- return namespace;
- }
- const firebase$1 = createFirebaseNamespace();
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const logger$1 = new Logger('@firebase/app-compat');
-
- const name$7 = "@firebase/app-compat";
- const version$7 = "0.2.11";
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function registerCoreComponents(variant) {
- // Register `app` package.
- registerVersion(name$7, version$7, variant);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // Firebase Lite detection
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- if (isBrowser() && self.firebase !== undefined) {
- logger$1.warn(`
- Warning: Firebase is already defined in the global scope. Please make sure
- Firebase library is only loaded once.
- `);
- // eslint-disable-next-line
- const sdkVersion = self.firebase.SDK_VERSION;
- if (sdkVersion && sdkVersion.indexOf('LITE') >= 0) {
- logger$1.warn(`
- Warning: You are trying to load Firebase while using Firebase Performance standalone script.
- You should load Firebase Performance with this instance of Firebase to avoid loading duplicate code.
- `);
- }
- }
- const firebase = firebase$1;
- registerCoreComponents();
-
- var name$6 = "firebase";
- var version$6 = "9.22.1";
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- firebase.registerVersion(name$6, version$6, 'app-compat');
-
- const instanceOfAny = (object, constructors) => constructors.some((c) => object instanceof c);
-
- let idbProxyableTypes;
- let cursorAdvanceMethods;
- // This is a function to prevent it throwing up in node environments.
- function getIdbProxyableTypes() {
- return (idbProxyableTypes ||
- (idbProxyableTypes = [
- IDBDatabase,
- IDBObjectStore,
- IDBIndex,
- IDBCursor,
- IDBTransaction,
- ]));
- }
- // This is a function to prevent it throwing up in node environments.
- function getCursorAdvanceMethods() {
- return (cursorAdvanceMethods ||
- (cursorAdvanceMethods = [
- IDBCursor.prototype.advance,
- IDBCursor.prototype.continue,
- IDBCursor.prototype.continuePrimaryKey,
- ]));
- }
- const cursorRequestMap = new WeakMap();
- const transactionDoneMap = new WeakMap();
- const transactionStoreNamesMap = new WeakMap();
- const transformCache = new WeakMap();
- const reverseTransformCache = new WeakMap();
- function promisifyRequest(request) {
- const promise = new Promise((resolve, reject) => {
- const unlisten = () => {
- request.removeEventListener('success', success);
- request.removeEventListener('error', error);
- };
- const success = () => {
- resolve(wrap(request.result));
- unlisten();
- };
- const error = () => {
- reject(request.error);
- unlisten();
- };
- request.addEventListener('success', success);
- request.addEventListener('error', error);
- });
- promise
- .then((value) => {
- // Since cursoring reuses the IDBRequest (*sigh*), we cache it for later retrieval
- // (see wrapFunction).
- if (value instanceof IDBCursor) {
- cursorRequestMap.set(value, request);
- }
- // Catching to avoid "Uncaught Promise exceptions"
- })
- .catch(() => { });
- // This mapping exists in reverseTransformCache but doesn't doesn't exist in transformCache. This
- // is because we create many promises from a single IDBRequest.
- reverseTransformCache.set(promise, request);
- return promise;
- }
- function cacheDonePromiseForTransaction(tx) {
- // Early bail if we've already created a done promise for this transaction.
- if (transactionDoneMap.has(tx))
- return;
- const done = new Promise((resolve, reject) => {
- const unlisten = () => {
- tx.removeEventListener('complete', complete);
- tx.removeEventListener('error', error);
- tx.removeEventListener('abort', error);
- };
- const complete = () => {
- resolve();
- unlisten();
- };
- const error = () => {
- reject(tx.error || new DOMException('AbortError', 'AbortError'));
- unlisten();
- };
- tx.addEventListener('complete', complete);
- tx.addEventListener('error', error);
- tx.addEventListener('abort', error);
- });
- // Cache it for later retrieval.
- transactionDoneMap.set(tx, done);
- }
- let idbProxyTraps = {
- get(target, prop, receiver) {
- if (target instanceof IDBTransaction) {
- // Special handling for transaction.done.
- if (prop === 'done')
- return transactionDoneMap.get(target);
- // Polyfill for objectStoreNames because of Edge.
- if (prop === 'objectStoreNames') {
- return target.objectStoreNames || transactionStoreNamesMap.get(target);
- }
- // Make tx.store return the only store in the transaction, or undefined if there are many.
- if (prop === 'store') {
- return receiver.objectStoreNames[1]
- ? undefined
- : receiver.objectStore(receiver.objectStoreNames[0]);
- }
- }
- // Else transform whatever we get back.
- return wrap(target[prop]);
- },
- set(target, prop, value) {
- target[prop] = value;
- return true;
- },
- has(target, prop) {
- if (target instanceof IDBTransaction &&
- (prop === 'done' || prop === 'store')) {
- return true;
- }
- return prop in target;
- },
- };
- function replaceTraps(callback) {
- idbProxyTraps = callback(idbProxyTraps);
- }
- function wrapFunction(func) {
- // Due to expected object equality (which is enforced by the caching in `wrap`), we
- // only create one new func per func.
- // Edge doesn't support objectStoreNames (booo), so we polyfill it here.
- if (func === IDBDatabase.prototype.transaction &&
- !('objectStoreNames' in IDBTransaction.prototype)) {
- return function (storeNames, ...args) {
- const tx = func.call(unwrap$1(this), storeNames, ...args);
- transactionStoreNamesMap.set(tx, storeNames.sort ? storeNames.sort() : [storeNames]);
- return wrap(tx);
- };
- }
- // Cursor methods are special, as the behaviour is a little more different to standard IDB. In
- // IDB, you advance the cursor and wait for a new 'success' on the IDBRequest that gave you the
- // cursor. It's kinda like a promise that can resolve with many values. That doesn't make sense
- // with real promises, so each advance methods returns a new promise for the cursor object, or
- // undefined if the end of the cursor has been reached.
- if (getCursorAdvanceMethods().includes(func)) {
- return function (...args) {
- // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
- // the original object.
- func.apply(unwrap$1(this), args);
- return wrap(cursorRequestMap.get(this));
- };
- }
- return function (...args) {
- // Calling the original function with the proxy as 'this' causes ILLEGAL INVOCATION, so we use
- // the original object.
- return wrap(func.apply(unwrap$1(this), args));
- };
- }
- function transformCachableValue(value) {
- if (typeof value === 'function')
- return wrapFunction(value);
- // This doesn't return, it just creates a 'done' promise for the transaction,
- // which is later returned for transaction.done (see idbObjectHandler).
- if (value instanceof IDBTransaction)
- cacheDonePromiseForTransaction(value);
- if (instanceOfAny(value, getIdbProxyableTypes()))
- return new Proxy(value, idbProxyTraps);
- // Return the same value back if we're not going to transform it.
- return value;
- }
- function wrap(value) {
- // We sometimes generate multiple promises from a single IDBRequest (eg when cursoring), because
- // IDB is weird and a single IDBRequest can yield many responses, so these can't be cached.
- if (value instanceof IDBRequest)
- return promisifyRequest(value);
- // If we've already transformed this value before, reuse the transformed value.
- // This is faster, but it also provides object equality.
- if (transformCache.has(value))
- return transformCache.get(value);
- const newValue = transformCachableValue(value);
- // Not all types are transformed.
- // These may be primitive types, so they can't be WeakMap keys.
- if (newValue !== value) {
- transformCache.set(value, newValue);
- reverseTransformCache.set(newValue, value);
- }
- return newValue;
- }
- const unwrap$1 = (value) => reverseTransformCache.get(value);
-
- /**
- * Open a database.
- *
- * @param name Name of the database.
- * @param version Schema version.
- * @param callbacks Additional callbacks.
- */
- function openDB(name, version, { blocked, upgrade, blocking, terminated } = {}) {
- const request = indexedDB.open(name, version);
- const openPromise = wrap(request);
- if (upgrade) {
- request.addEventListener('upgradeneeded', (event) => {
- upgrade(wrap(request.result), event.oldVersion, event.newVersion, wrap(request.transaction));
- });
- }
- if (blocked)
- request.addEventListener('blocked', () => blocked());
- openPromise
- .then((db) => {
- if (terminated)
- db.addEventListener('close', () => terminated());
- if (blocking)
- db.addEventListener('versionchange', () => blocking());
- })
- .catch(() => { });
- return openPromise;
- }
-
- const readMethods = ['get', 'getKey', 'getAll', 'getAllKeys', 'count'];
- const writeMethods = ['put', 'add', 'delete', 'clear'];
- const cachedMethods = new Map();
- function getMethod(target, prop) {
- if (!(target instanceof IDBDatabase &&
- !(prop in target) &&
- typeof prop === 'string')) {
- return;
- }
- if (cachedMethods.get(prop))
- return cachedMethods.get(prop);
- const targetFuncName = prop.replace(/FromIndex$/, '');
- const useIndex = prop !== targetFuncName;
- const isWrite = writeMethods.includes(targetFuncName);
- if (
- // Bail if the target doesn't exist on the target. Eg, getAll isn't in Edge.
- !(targetFuncName in (useIndex ? IDBIndex : IDBObjectStore).prototype) ||
- !(isWrite || readMethods.includes(targetFuncName))) {
- return;
- }
- const method = async function (storeName, ...args) {
- // isWrite ? 'readwrite' : undefined gzipps better, but fails in Edge :(
- const tx = this.transaction(storeName, isWrite ? 'readwrite' : 'readonly');
- let target = tx.store;
- if (useIndex)
- target = target.index(args.shift());
- // Must reject if op rejects.
- // If it's a write operation, must reject if tx.done rejects.
- // Must reject with op rejection first.
- // Must resolve with op value.
- // Must handle both promises (no unhandled rejections)
- return (await Promise.all([
- target[targetFuncName](...args),
- isWrite && tx.done,
- ]))[0];
- };
- cachedMethods.set(prop, method);
- return method;
- }
- replaceTraps((oldTraps) => ({
- ...oldTraps,
- get: (target, prop, receiver) => getMethod(target, prop) || oldTraps.get(target, prop, receiver),
- has: (target, prop) => !!getMethod(target, prop) || oldTraps.has(target, prop),
- }));
-
- const name$5 = "@firebase/installations";
- const version$5 = "0.6.4";
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const PENDING_TIMEOUT_MS = 10000;
- const PACKAGE_VERSION = `w:${version$5}`;
- const INTERNAL_AUTH_VERSION = 'FIS_v2';
- const INSTALLATIONS_API_URL = 'https://firebaseinstallations.googleapis.com/v1';
- const TOKEN_EXPIRATION_BUFFER = 60 * 60 * 1000; // One hour
- const SERVICE$1 = 'installations';
- const SERVICE_NAME$1 = 'Installations';
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const ERROR_DESCRIPTION_MAP$1 = {
- ["missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */]: 'Missing App configuration value: "{$valueName}"',
- ["not-registered" /* ErrorCode.NOT_REGISTERED */]: 'Firebase Installation is not registered.',
- ["installation-not-found" /* ErrorCode.INSTALLATION_NOT_FOUND */]: 'Firebase Installation not found.',
- ["request-failed" /* ErrorCode.REQUEST_FAILED */]: '{$requestName} request failed with error "{$serverCode} {$serverStatus}: {$serverMessage}"',
- ["app-offline" /* ErrorCode.APP_OFFLINE */]: 'Could not process request. Application offline.',
- ["delete-pending-registration" /* ErrorCode.DELETE_PENDING_REGISTRATION */]: "Can't delete installation while there is a pending registration request."
- };
- const ERROR_FACTORY$1 = new ErrorFactory(SERVICE$1, SERVICE_NAME$1, ERROR_DESCRIPTION_MAP$1);
- /** Returns true if error is a FirebaseError that is based on an error from the server. */
- function isServerError(error) {
- return (error instanceof FirebaseError &&
- error.code.includes("request-failed" /* ErrorCode.REQUEST_FAILED */));
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function getInstallationsEndpoint({ projectId }) {
- return `${INSTALLATIONS_API_URL}/projects/${projectId}/installations`;
- }
- function extractAuthTokenInfoFromResponse(response) {
- return {
- token: response.token,
- requestStatus: 2 /* RequestStatus.COMPLETED */,
- expiresIn: getExpiresInFromResponseExpiresIn(response.expiresIn),
- creationTime: Date.now()
- };
- }
- async function getErrorFromResponse(requestName, response) {
- const responseJson = await response.json();
- const errorData = responseJson.error;
- return ERROR_FACTORY$1.create("request-failed" /* ErrorCode.REQUEST_FAILED */, {
- requestName,
- serverCode: errorData.code,
- serverMessage: errorData.message,
- serverStatus: errorData.status
- });
- }
- function getHeaders({ apiKey }) {
- return new Headers({
- 'Content-Type': 'application/json',
- Accept: 'application/json',
- 'x-goog-api-key': apiKey
- });
- }
- function getHeadersWithAuth(appConfig, { refreshToken }) {
- const headers = getHeaders(appConfig);
- headers.append('Authorization', getAuthorizationHeader(refreshToken));
- return headers;
- }
- /**
- * Calls the passed in fetch wrapper and returns the response.
- * If the returned response has a status of 5xx, re-runs the function once and
- * returns the response.
- */
- async function retryIfServerError(fn) {
- const result = await fn();
- if (result.status >= 500 && result.status < 600) {
- // Internal Server Error. Retry request.
- return fn();
- }
- return result;
- }
- function getExpiresInFromResponseExpiresIn(responseExpiresIn) {
- // This works because the server will never respond with fractions of a second.
- return Number(responseExpiresIn.replace('s', '000'));
- }
- function getAuthorizationHeader(refreshToken) {
- return `${INTERNAL_AUTH_VERSION} ${refreshToken}`;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function createInstallationRequest({ appConfig, heartbeatServiceProvider }, { fid }) {
- const endpoint = getInstallationsEndpoint(appConfig);
- const headers = getHeaders(appConfig);
- // If heartbeat service exists, add the heartbeat string to the header.
- const heartbeatService = heartbeatServiceProvider.getImmediate({
- optional: true
- });
- if (heartbeatService) {
- const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();
- if (heartbeatsHeader) {
- headers.append('x-firebase-client', heartbeatsHeader);
- }
- }
- const body = {
- fid,
- authVersion: INTERNAL_AUTH_VERSION,
- appId: appConfig.appId,
- sdkVersion: PACKAGE_VERSION
- };
- const request = {
- method: 'POST',
- headers,
- body: JSON.stringify(body)
- };
- const response = await retryIfServerError(() => fetch(endpoint, request));
- if (response.ok) {
- const responseValue = await response.json();
- const registeredInstallationEntry = {
- fid: responseValue.fid || fid,
- registrationStatus: 2 /* RequestStatus.COMPLETED */,
- refreshToken: responseValue.refreshToken,
- authToken: extractAuthTokenInfoFromResponse(responseValue.authToken)
- };
- return registeredInstallationEntry;
- }
- else {
- throw await getErrorFromResponse('Create Installation', response);
- }
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /** Returns a promise that resolves after given time passes. */
- function sleep(ms) {
- return new Promise(resolve => {
- setTimeout(resolve, ms);
- });
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function bufferToBase64UrlSafe(array) {
- const b64 = btoa(String.fromCharCode(...array));
- return b64.replace(/\+/g, '-').replace(/\//g, '_');
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const VALID_FID_PATTERN = /^[cdef][\w-]{21}$/;
- const INVALID_FID = '';
- /**
- * Generates a new FID using random values from Web Crypto API.
- * Returns an empty string if FID generation fails for any reason.
- */
- function generateFid() {
- try {
- // A valid FID has exactly 22 base64 characters, which is 132 bits, or 16.5
- // bytes. our implementation generates a 17 byte array instead.
- const fidByteArray = new Uint8Array(17);
- const crypto = self.crypto || self.msCrypto;
- crypto.getRandomValues(fidByteArray);
- // Replace the first 4 random bits with the constant FID header of 0b0111.
- fidByteArray[0] = 0b01110000 + (fidByteArray[0] % 0b00010000);
- const fid = encode(fidByteArray);
- return VALID_FID_PATTERN.test(fid) ? fid : INVALID_FID;
- }
- catch (_a) {
- // FID generation errored
- return INVALID_FID;
- }
- }
- /** Converts a FID Uint8Array to a base64 string representation. */
- function encode(fidByteArray) {
- const b64String = bufferToBase64UrlSafe(fidByteArray);
- // Remove the 23rd character that was added because of the extra 4 bits at the
- // end of our 17 byte array, and the '=' padding.
- return b64String.substr(0, 22);
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /** Returns a string key that can be used to identify the app. */
- function getKey(appConfig) {
- return `${appConfig.appName}!${appConfig.appId}`;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const fidChangeCallbacks = new Map();
- /**
- * Calls the onIdChange callbacks with the new FID value, and broadcasts the
- * change to other tabs.
- */
- function fidChanged(appConfig, fid) {
- const key = getKey(appConfig);
- callFidChangeCallbacks(key, fid);
- broadcastFidChange(key, fid);
- }
- function callFidChangeCallbacks(key, fid) {
- const callbacks = fidChangeCallbacks.get(key);
- if (!callbacks) {
- return;
- }
- for (const callback of callbacks) {
- callback(fid);
- }
- }
- function broadcastFidChange(key, fid) {
- const channel = getBroadcastChannel();
- if (channel) {
- channel.postMessage({ key, fid });
- }
- closeBroadcastChannel();
- }
- let broadcastChannel = null;
- /** Opens and returns a BroadcastChannel if it is supported by the browser. */
- function getBroadcastChannel() {
- if (!broadcastChannel && 'BroadcastChannel' in self) {
- broadcastChannel = new BroadcastChannel('[Firebase] FID Change');
- broadcastChannel.onmessage = e => {
- callFidChangeCallbacks(e.data.key, e.data.fid);
- };
- }
- return broadcastChannel;
- }
- function closeBroadcastChannel() {
- if (fidChangeCallbacks.size === 0 && broadcastChannel) {
- broadcastChannel.close();
- broadcastChannel = null;
- }
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const DATABASE_NAME = 'firebase-installations-database';
- const DATABASE_VERSION = 1;
- const OBJECT_STORE_NAME = 'firebase-installations-store';
- let dbPromise = null;
- function getDbPromise() {
- if (!dbPromise) {
- dbPromise = openDB(DATABASE_NAME, DATABASE_VERSION, {
- upgrade: (db, oldVersion) => {
- // We don't use 'break' in this switch statement, the fall-through
- // behavior is what we want, because if there are multiple versions between
- // the old version and the current version, we want ALL the migrations
- // that correspond to those versions to run, not only the last one.
- // eslint-disable-next-line default-case
- switch (oldVersion) {
- case 0:
- db.createObjectStore(OBJECT_STORE_NAME);
- }
- }
- });
- }
- return dbPromise;
- }
- /** Assigns or overwrites the record for the given key with the given value. */
- async function set$1(appConfig, value) {
- const key = getKey(appConfig);
- const db = await getDbPromise();
- const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
- const objectStore = tx.objectStore(OBJECT_STORE_NAME);
- const oldValue = (await objectStore.get(key));
- await objectStore.put(value, key);
- await tx.done;
- if (!oldValue || oldValue.fid !== value.fid) {
- fidChanged(appConfig, value.fid);
- }
- return value;
- }
- /** Removes record(s) from the objectStore that match the given key. */
- async function remove$1(appConfig) {
- const key = getKey(appConfig);
- const db = await getDbPromise();
- const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
- await tx.objectStore(OBJECT_STORE_NAME).delete(key);
- await tx.done;
- }
- /**
- * Atomically updates a record with the result of updateFn, which gets
- * called with the current value. If newValue is undefined, the record is
- * deleted instead.
- * @return Updated value
- */
- async function update(appConfig, updateFn) {
- const key = getKey(appConfig);
- const db = await getDbPromise();
- const tx = db.transaction(OBJECT_STORE_NAME, 'readwrite');
- const store = tx.objectStore(OBJECT_STORE_NAME);
- const oldValue = (await store.get(key));
- const newValue = updateFn(oldValue);
- if (newValue === undefined) {
- await store.delete(key);
- }
- else {
- await store.put(newValue, key);
- }
- await tx.done;
- if (newValue && (!oldValue || oldValue.fid !== newValue.fid)) {
- fidChanged(appConfig, newValue.fid);
- }
- return newValue;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Updates and returns the InstallationEntry from the database.
- * Also triggers a registration request if it is necessary and possible.
- */
- async function getInstallationEntry(installations) {
- let registrationPromise;
- const installationEntry = await update(installations.appConfig, oldEntry => {
- const installationEntry = updateOrCreateInstallationEntry(oldEntry);
- const entryWithPromise = triggerRegistrationIfNecessary(installations, installationEntry);
- registrationPromise = entryWithPromise.registrationPromise;
- return entryWithPromise.installationEntry;
- });
- if (installationEntry.fid === INVALID_FID) {
- // FID generation failed. Waiting for the FID from the server.
- return { installationEntry: await registrationPromise };
- }
- return {
- installationEntry,
- registrationPromise
- };
- }
- /**
- * Creates a new Installation Entry if one does not exist.
- * Also clears timed out pending requests.
- */
- function updateOrCreateInstallationEntry(oldEntry) {
- const entry = oldEntry || {
- fid: generateFid(),
- registrationStatus: 0 /* RequestStatus.NOT_STARTED */
- };
- return clearTimedOutRequest(entry);
- }
- /**
- * If the Firebase Installation is not registered yet, this will trigger the
- * registration and return an InProgressInstallationEntry.
- *
- * If registrationPromise does not exist, the installationEntry is guaranteed
- * to be registered.
- */
- function triggerRegistrationIfNecessary(installations, installationEntry) {
- if (installationEntry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {
- if (!navigator.onLine) {
- // Registration required but app is offline.
- const registrationPromiseWithError = Promise.reject(ERROR_FACTORY$1.create("app-offline" /* ErrorCode.APP_OFFLINE */));
- return {
- installationEntry,
- registrationPromise: registrationPromiseWithError
- };
- }
- // Try registering. Change status to IN_PROGRESS.
- const inProgressEntry = {
- fid: installationEntry.fid,
- registrationStatus: 1 /* RequestStatus.IN_PROGRESS */,
- registrationTime: Date.now()
- };
- const registrationPromise = registerInstallation(installations, inProgressEntry);
- return { installationEntry: inProgressEntry, registrationPromise };
- }
- else if (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {
- return {
- installationEntry,
- registrationPromise: waitUntilFidRegistration(installations)
- };
- }
- else {
- return { installationEntry };
- }
- }
- /** This will be executed only once for each new Firebase Installation. */
- async function registerInstallation(installations, installationEntry) {
- try {
- const registeredInstallationEntry = await createInstallationRequest(installations, installationEntry);
- return set$1(installations.appConfig, registeredInstallationEntry);
- }
- catch (e) {
- if (isServerError(e) && e.customData.serverCode === 409) {
- // Server returned a "FID can not be used" error.
- // Generate a new ID next time.
- await remove$1(installations.appConfig);
- }
- else {
- // Registration failed. Set FID as not registered.
- await set$1(installations.appConfig, {
- fid: installationEntry.fid,
- registrationStatus: 0 /* RequestStatus.NOT_STARTED */
- });
- }
- throw e;
- }
- }
- /** Call if FID registration is pending in another request. */
- async function waitUntilFidRegistration(installations) {
- // Unfortunately, there is no way of reliably observing when a value in
- // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
- // so we need to poll.
- let entry = await updateInstallationRequest(installations.appConfig);
- while (entry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */) {
- // createInstallation request still in progress.
- await sleep(100);
- entry = await updateInstallationRequest(installations.appConfig);
- }
- if (entry.registrationStatus === 0 /* RequestStatus.NOT_STARTED */) {
- // The request timed out or failed in a different call. Try again.
- const { installationEntry, registrationPromise } = await getInstallationEntry(installations);
- if (registrationPromise) {
- return registrationPromise;
- }
- else {
- // if there is no registrationPromise, entry is registered.
- return installationEntry;
- }
- }
- return entry;
- }
- /**
- * Called only if there is a CreateInstallation request in progress.
- *
- * Updates the InstallationEntry in the DB based on the status of the
- * CreateInstallation request.
- *
- * Returns the updated InstallationEntry.
- */
- function updateInstallationRequest(appConfig) {
- return update(appConfig, oldEntry => {
- if (!oldEntry) {
- throw ERROR_FACTORY$1.create("installation-not-found" /* ErrorCode.INSTALLATION_NOT_FOUND */);
- }
- return clearTimedOutRequest(oldEntry);
- });
- }
- function clearTimedOutRequest(entry) {
- if (hasInstallationRequestTimedOut(entry)) {
- return {
- fid: entry.fid,
- registrationStatus: 0 /* RequestStatus.NOT_STARTED */
- };
- }
- return entry;
- }
- function hasInstallationRequestTimedOut(installationEntry) {
- return (installationEntry.registrationStatus === 1 /* RequestStatus.IN_PROGRESS */ &&
- installationEntry.registrationTime + PENDING_TIMEOUT_MS < Date.now());
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function generateAuthTokenRequest({ appConfig, heartbeatServiceProvider }, installationEntry) {
- const endpoint = getGenerateAuthTokenEndpoint(appConfig, installationEntry);
- const headers = getHeadersWithAuth(appConfig, installationEntry);
- // If heartbeat service exists, add the heartbeat string to the header.
- const heartbeatService = heartbeatServiceProvider.getImmediate({
- optional: true
- });
- if (heartbeatService) {
- const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader();
- if (heartbeatsHeader) {
- headers.append('x-firebase-client', heartbeatsHeader);
- }
- }
- const body = {
- installation: {
- sdkVersion: PACKAGE_VERSION,
- appId: appConfig.appId
- }
- };
- const request = {
- method: 'POST',
- headers,
- body: JSON.stringify(body)
- };
- const response = await retryIfServerError(() => fetch(endpoint, request));
- if (response.ok) {
- const responseValue = await response.json();
- const completedAuthToken = extractAuthTokenInfoFromResponse(responseValue);
- return completedAuthToken;
- }
- else {
- throw await getErrorFromResponse('Generate Auth Token', response);
- }
- }
- function getGenerateAuthTokenEndpoint(appConfig, { fid }) {
- return `${getInstallationsEndpoint(appConfig)}/${fid}/authTokens:generate`;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Returns a valid authentication token for the installation. Generates a new
- * token if one doesn't exist, is expired or about to expire.
- *
- * Should only be called if the Firebase Installation is registered.
- */
- async function refreshAuthToken(installations, forceRefresh = false) {
- let tokenPromise;
- const entry = await update(installations.appConfig, oldEntry => {
- if (!isEntryRegistered(oldEntry)) {
- throw ERROR_FACTORY$1.create("not-registered" /* ErrorCode.NOT_REGISTERED */);
- }
- const oldAuthToken = oldEntry.authToken;
- if (!forceRefresh && isAuthTokenValid(oldAuthToken)) {
- // There is a valid token in the DB.
- return oldEntry;
- }
- else if (oldAuthToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) {
- // There already is a token request in progress.
- tokenPromise = waitUntilAuthTokenRequest(installations, forceRefresh);
- return oldEntry;
- }
- else {
- // No token or token expired.
- if (!navigator.onLine) {
- throw ERROR_FACTORY$1.create("app-offline" /* ErrorCode.APP_OFFLINE */);
- }
- const inProgressEntry = makeAuthTokenRequestInProgressEntry(oldEntry);
- tokenPromise = fetchAuthTokenFromServer(installations, inProgressEntry);
- return inProgressEntry;
- }
- });
- const authToken = tokenPromise
- ? await tokenPromise
- : entry.authToken;
- return authToken;
- }
- /**
- * Call only if FID is registered and Auth Token request is in progress.
- *
- * Waits until the current pending request finishes. If the request times out,
- * tries once in this thread as well.
- */
- async function waitUntilAuthTokenRequest(installations, forceRefresh) {
- // Unfortunately, there is no way of reliably observing when a value in
- // IndexedDB changes (yet, see https://github.com/WICG/indexed-db-observers),
- // so we need to poll.
- let entry = await updateAuthTokenRequest(installations.appConfig);
- while (entry.authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */) {
- // generateAuthToken still in progress.
- await sleep(100);
- entry = await updateAuthTokenRequest(installations.appConfig);
- }
- const authToken = entry.authToken;
- if (authToken.requestStatus === 0 /* RequestStatus.NOT_STARTED */) {
- // The request timed out or failed in a different call. Try again.
- return refreshAuthToken(installations, forceRefresh);
- }
- else {
- return authToken;
- }
- }
- /**
- * Called only if there is a GenerateAuthToken request in progress.
- *
- * Updates the InstallationEntry in the DB based on the status of the
- * GenerateAuthToken request.
- *
- * Returns the updated InstallationEntry.
- */
- function updateAuthTokenRequest(appConfig) {
- return update(appConfig, oldEntry => {
- if (!isEntryRegistered(oldEntry)) {
- throw ERROR_FACTORY$1.create("not-registered" /* ErrorCode.NOT_REGISTERED */);
- }
- const oldAuthToken = oldEntry.authToken;
- if (hasAuthTokenRequestTimedOut(oldAuthToken)) {
- return Object.assign(Object.assign({}, oldEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } });
- }
- return oldEntry;
- });
- }
- async function fetchAuthTokenFromServer(installations, installationEntry) {
- try {
- const authToken = await generateAuthTokenRequest(installations, installationEntry);
- const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken });
- await set$1(installations.appConfig, updatedInstallationEntry);
- return authToken;
- }
- catch (e) {
- if (isServerError(e) &&
- (e.customData.serverCode === 401 || e.customData.serverCode === 404)) {
- // Server returned a "FID not found" or a "Invalid authentication" error.
- // Generate a new ID next time.
- await remove$1(installations.appConfig);
- }
- else {
- const updatedInstallationEntry = Object.assign(Object.assign({}, installationEntry), { authToken: { requestStatus: 0 /* RequestStatus.NOT_STARTED */ } });
- await set$1(installations.appConfig, updatedInstallationEntry);
- }
- throw e;
- }
- }
- function isEntryRegistered(installationEntry) {
- return (installationEntry !== undefined &&
- installationEntry.registrationStatus === 2 /* RequestStatus.COMPLETED */);
- }
- function isAuthTokenValid(authToken) {
- return (authToken.requestStatus === 2 /* RequestStatus.COMPLETED */ &&
- !isAuthTokenExpired(authToken));
- }
- function isAuthTokenExpired(authToken) {
- const now = Date.now();
- return (now < authToken.creationTime ||
- authToken.creationTime + authToken.expiresIn < now + TOKEN_EXPIRATION_BUFFER);
- }
- /** Returns an updated InstallationEntry with an InProgressAuthToken. */
- function makeAuthTokenRequestInProgressEntry(oldEntry) {
- const inProgressAuthToken = {
- requestStatus: 1 /* RequestStatus.IN_PROGRESS */,
- requestTime: Date.now()
- };
- return Object.assign(Object.assign({}, oldEntry), { authToken: inProgressAuthToken });
- }
- function hasAuthTokenRequestTimedOut(authToken) {
- return (authToken.requestStatus === 1 /* RequestStatus.IN_PROGRESS */ &&
- authToken.requestTime + PENDING_TIMEOUT_MS < Date.now());
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Creates a Firebase Installation if there isn't one for the app and
- * returns the Installation ID.
- * @param installations - The `Installations` instance.
- *
- * @public
- */
- async function getId(installations) {
- const installationsImpl = installations;
- const { installationEntry, registrationPromise } = await getInstallationEntry(installationsImpl);
- if (registrationPromise) {
- registrationPromise.catch(console.error);
- }
- else {
- // If the installation is already registered, update the authentication
- // token if needed.
- refreshAuthToken(installationsImpl).catch(console.error);
- }
- return installationEntry.fid;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Returns a Firebase Installations auth token, identifying the current
- * Firebase Installation.
- * @param installations - The `Installations` instance.
- * @param forceRefresh - Force refresh regardless of token expiration.
- *
- * @public
- */
- async function getToken(installations, forceRefresh = false) {
- const installationsImpl = installations;
- await completeInstallationRegistration(installationsImpl);
- // At this point we either have a Registered Installation in the DB, or we've
- // already thrown an error.
- const authToken = await refreshAuthToken(installationsImpl, forceRefresh);
- return authToken.token;
- }
- async function completeInstallationRegistration(installations) {
- const { registrationPromise } = await getInstallationEntry(installations);
- if (registrationPromise) {
- // A createInstallation request is in progress. Wait until it finishes.
- await registrationPromise;
- }
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function extractAppConfig(app) {
- if (!app || !app.options) {
- throw getMissingValueError('App Configuration');
- }
- if (!app.name) {
- throw getMissingValueError('App Name');
- }
- // Required app config keys
- const configKeys = [
- 'projectId',
- 'apiKey',
- 'appId'
- ];
- for (const keyName of configKeys) {
- if (!app.options[keyName]) {
- throw getMissingValueError(keyName);
- }
- }
- return {
- appName: app.name,
- projectId: app.options.projectId,
- apiKey: app.options.apiKey,
- appId: app.options.appId
- };
- }
- function getMissingValueError(valueName) {
- return ERROR_FACTORY$1.create("missing-app-config-values" /* ErrorCode.MISSING_APP_CONFIG_VALUES */, {
- valueName
- });
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const INSTALLATIONS_NAME = 'installations';
- const INSTALLATIONS_NAME_INTERNAL = 'installations-internal';
- const publicFactory = (container) => {
- const app = container.getProvider('app').getImmediate();
- // Throws if app isn't configured properly.
- const appConfig = extractAppConfig(app);
- const heartbeatServiceProvider = _getProvider(app, 'heartbeat');
- const installationsImpl = {
- app,
- appConfig,
- heartbeatServiceProvider,
- _delete: () => Promise.resolve()
- };
- return installationsImpl;
- };
- const internalFactory = (container) => {
- const app = container.getProvider('app').getImmediate();
- // Internal FIS instance relies on public FIS instance.
- const installations = _getProvider(app, INSTALLATIONS_NAME).getImmediate();
- const installationsInternal = {
- getId: () => getId(installations),
- getToken: (forceRefresh) => getToken(installations, forceRefresh)
- };
- return installationsInternal;
- };
- function registerInstallations() {
- _registerComponent(new Component(INSTALLATIONS_NAME, publicFactory, "PUBLIC" /* ComponentType.PUBLIC */));
- _registerComponent(new Component(INSTALLATIONS_NAME_INTERNAL, internalFactory, "PRIVATE" /* ComponentType.PRIVATE */));
- }
-
- /**
- * Firebase Installations
- *
- * @packageDocumentation
- */
- registerInstallations();
- registerVersion(name$5, version$5);
- // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
- registerVersion(name$5, version$5, 'esm2017');
-
- const name$4 = "@firebase/performance";
- const version$4 = "0.6.4";
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const SDK_VERSION = version$4;
- /** The prefix for start User Timing marks used for creating Traces. */
- const TRACE_START_MARK_PREFIX = 'FB-PERF-TRACE-START';
- /** The prefix for stop User Timing marks used for creating Traces. */
- const TRACE_STOP_MARK_PREFIX = 'FB-PERF-TRACE-STOP';
- /** The prefix for User Timing measure used for creating Traces. */
- const TRACE_MEASURE_PREFIX = 'FB-PERF-TRACE-MEASURE';
- /** The prefix for out of the box page load Trace name. */
- const OOB_TRACE_PAGE_LOAD_PREFIX = '_wt_';
- const FIRST_PAINT_COUNTER_NAME = '_fp';
- const FIRST_CONTENTFUL_PAINT_COUNTER_NAME = '_fcp';
- const FIRST_INPUT_DELAY_COUNTER_NAME = '_fid';
- const CONFIG_LOCAL_STORAGE_KEY = '@firebase/performance/config';
- const CONFIG_EXPIRY_LOCAL_STORAGE_KEY = '@firebase/performance/configexpire';
- const SERVICE = 'performance';
- const SERVICE_NAME = 'Performance';
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const ERROR_DESCRIPTION_MAP = {
- ["trace started" /* ErrorCode.TRACE_STARTED_BEFORE */]: 'Trace {$traceName} was started before.',
- ["trace stopped" /* ErrorCode.TRACE_STOPPED_BEFORE */]: 'Trace {$traceName} is not running.',
- ["nonpositive trace startTime" /* ErrorCode.NONPOSITIVE_TRACE_START_TIME */]: 'Trace {$traceName} startTime should be positive.',
- ["nonpositive trace duration" /* ErrorCode.NONPOSITIVE_TRACE_DURATION */]: 'Trace {$traceName} duration should be positive.',
- ["no window" /* ErrorCode.NO_WINDOW */]: 'Window is not available.',
- ["no app id" /* ErrorCode.NO_APP_ID */]: 'App id is not available.',
- ["no project id" /* ErrorCode.NO_PROJECT_ID */]: 'Project id is not available.',
- ["no api key" /* ErrorCode.NO_API_KEY */]: 'Api key is not available.',
- ["invalid cc log" /* ErrorCode.INVALID_CC_LOG */]: 'Attempted to queue invalid cc event',
- ["FB not default" /* ErrorCode.FB_NOT_DEFAULT */]: 'Performance can only start when Firebase app instance is the default one.',
- ["RC response not ok" /* ErrorCode.RC_NOT_OK */]: 'RC response is not ok',
- ["invalid attribute name" /* ErrorCode.INVALID_ATTRIBUTE_NAME */]: 'Attribute name {$attributeName} is invalid.',
- ["invalid attribute value" /* ErrorCode.INVALID_ATTRIBUTE_VALUE */]: 'Attribute value {$attributeValue} is invalid.',
- ["invalid custom metric name" /* ErrorCode.INVALID_CUSTOM_METRIC_NAME */]: 'Custom metric name {$customMetricName} is invalid',
- ["invalid String merger input" /* ErrorCode.INVALID_STRING_MERGER_PARAMETER */]: 'Input for String merger is invalid, contact support team to resolve.',
- ["already initialized" /* ErrorCode.ALREADY_INITIALIZED */]: 'initializePerformance() has already been called with ' +
- 'different options. To avoid this error, call initializePerformance() with the ' +
- 'same options as when it was originally called, or call getPerformance() to return the' +
- ' already initialized instance.'
- };
- const ERROR_FACTORY = new ErrorFactory(SERVICE, SERVICE_NAME, ERROR_DESCRIPTION_MAP);
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const consoleLogger = new Logger(SERVICE_NAME);
- consoleLogger.logLevel = LogLevel.INFO;
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- let apiInstance;
- let windowInstance;
- /**
- * This class holds a reference to various browser related objects injected by
- * set methods.
- */
- class Api {
- constructor(window) {
- this.window = window;
- if (!window) {
- throw ERROR_FACTORY.create("no window" /* ErrorCode.NO_WINDOW */);
- }
- this.performance = window.performance;
- this.PerformanceObserver = window.PerformanceObserver;
- this.windowLocation = window.location;
- this.navigator = window.navigator;
- this.document = window.document;
- if (this.navigator && this.navigator.cookieEnabled) {
- // If user blocks cookies on the browser, accessing localStorage will
- // throw an exception.
- this.localStorage = window.localStorage;
- }
- if (window.perfMetrics && window.perfMetrics.onFirstInputDelay) {
- this.onFirstInputDelay = window.perfMetrics.onFirstInputDelay;
- }
- }
- getUrl() {
- // Do not capture the string query part of url.
- return this.windowLocation.href.split('?')[0];
- }
- mark(name) {
- if (!this.performance || !this.performance.mark) {
- return;
- }
- this.performance.mark(name);
- }
- measure(measureName, mark1, mark2) {
- if (!this.performance || !this.performance.measure) {
- return;
- }
- this.performance.measure(measureName, mark1, mark2);
- }
- getEntriesByType(type) {
- if (!this.performance || !this.performance.getEntriesByType) {
- return [];
- }
- return this.performance.getEntriesByType(type);
- }
- getEntriesByName(name) {
- if (!this.performance || !this.performance.getEntriesByName) {
- return [];
- }
- return this.performance.getEntriesByName(name);
- }
- getTimeOrigin() {
- // Polyfill the time origin with performance.timing.navigationStart.
- return (this.performance &&
- (this.performance.timeOrigin || this.performance.timing.navigationStart));
- }
- requiredApisAvailable() {
- if (!fetch || !Promise || !areCookiesEnabled()) {
- consoleLogger.info('Firebase Performance cannot start if browser does not support fetch and Promise or cookie is disabled.');
- return false;
- }
- if (!isIndexedDBAvailable()) {
- consoleLogger.info('IndexedDB is not supported by current browswer');
- return false;
- }
- return true;
- }
- setupObserver(entryType, callback) {
- if (!this.PerformanceObserver) {
- return;
- }
- const observer = new this.PerformanceObserver(list => {
- for (const entry of list.getEntries()) {
- // `entry` is a PerformanceEntry instance.
- callback(entry);
- }
- });
- // Start observing the entry types you care about.
- observer.observe({ entryTypes: [entryType] });
- }
- static getInstance() {
- if (apiInstance === undefined) {
- apiInstance = new Api(windowInstance);
- }
- return apiInstance;
- }
- }
- function setupApi(window) {
- windowInstance = window;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- let iid;
- function getIidPromise(installationsService) {
- const iidPromise = installationsService.getId();
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- iidPromise.then((iidVal) => {
- iid = iidVal;
- });
- return iidPromise;
- }
- // This method should be used after the iid is retrieved by getIidPromise method.
- function getIid() {
- return iid;
- }
- function getAuthTokenPromise(installationsService) {
- const authTokenPromise = installationsService.getToken();
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- authTokenPromise.then((authTokenVal) => {
- });
- return authTokenPromise;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function mergeStrings(part1, part2) {
- const sizeDiff = part1.length - part2.length;
- if (sizeDiff < 0 || sizeDiff > 1) {
- throw ERROR_FACTORY.create("invalid String merger input" /* ErrorCode.INVALID_STRING_MERGER_PARAMETER */);
- }
- const resultArray = [];
- for (let i = 0; i < part1.length; i++) {
- resultArray.push(part1.charAt(i));
- if (part2.length > i) {
- resultArray.push(part2.charAt(i));
- }
- }
- return resultArray.join('');
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- let settingsServiceInstance;
- class SettingsService {
- constructor() {
- // The variable which controls logging of automatic traces and HTTP/S network monitoring.
- this.instrumentationEnabled = true;
- // The variable which controls logging of custom traces.
- this.dataCollectionEnabled = true;
- // Configuration flags set through remote config.
- this.loggingEnabled = false;
- // Sampling rate between 0 and 1.
- this.tracesSamplingRate = 1;
- this.networkRequestsSamplingRate = 1;
- // Address of logging service.
- this.logEndPointUrl = 'https://firebaselogging.googleapis.com/v0cc/log?format=json_proto';
- // Performance event transport endpoint URL which should be compatible with proto3.
- // New Address for transport service, not configurable via Remote Config.
- this.flTransportEndpointUrl = mergeStrings('hts/frbslgigp.ogepscmv/ieo/eaylg', 'tp:/ieaeogn-agolai.o/1frlglgc/o');
- this.transportKey = mergeStrings('AzSC8r6ReiGqFMyfvgow', 'Iayx0u-XT3vksVM-pIV');
- // Source type for performance event logs.
- this.logSource = 462;
- // Flags which control per session logging of traces and network requests.
- this.logTraceAfterSampling = false;
- this.logNetworkAfterSampling = false;
- // TTL of config retrieved from remote config in hours.
- this.configTimeToLive = 12;
- }
- getFlTransportFullUrl() {
- return this.flTransportEndpointUrl.concat('?key=', this.transportKey);
- }
- static getInstance() {
- if (settingsServiceInstance === undefined) {
- settingsServiceInstance = new SettingsService();
- }
- return settingsServiceInstance;
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- var VisibilityState;
- (function (VisibilityState) {
- VisibilityState[VisibilityState["UNKNOWN"] = 0] = "UNKNOWN";
- VisibilityState[VisibilityState["VISIBLE"] = 1] = "VISIBLE";
- VisibilityState[VisibilityState["HIDDEN"] = 2] = "HIDDEN";
- })(VisibilityState || (VisibilityState = {}));
- const RESERVED_ATTRIBUTE_PREFIXES = ['firebase_', 'google_', 'ga_'];
- const ATTRIBUTE_FORMAT_REGEX = new RegExp('^[a-zA-Z]\\w*$');
- const MAX_ATTRIBUTE_NAME_LENGTH = 40;
- const MAX_ATTRIBUTE_VALUE_LENGTH = 100;
- function getServiceWorkerStatus() {
- const navigator = Api.getInstance().navigator;
- if (navigator === null || navigator === void 0 ? void 0 : navigator.serviceWorker) {
- if (navigator.serviceWorker.controller) {
- return 2 /* ServiceWorkerStatus.CONTROLLED */;
- }
- else {
- return 3 /* ServiceWorkerStatus.UNCONTROLLED */;
- }
- }
- else {
- return 1 /* ServiceWorkerStatus.UNSUPPORTED */;
- }
- }
- function getVisibilityState() {
- const document = Api.getInstance().document;
- const visibilityState = document.visibilityState;
- switch (visibilityState) {
- case 'visible':
- return VisibilityState.VISIBLE;
- case 'hidden':
- return VisibilityState.HIDDEN;
- default:
- return VisibilityState.UNKNOWN;
- }
- }
- function getEffectiveConnectionType() {
- const navigator = Api.getInstance().navigator;
- const navigatorConnection = navigator.connection;
- const effectiveType = navigatorConnection && navigatorConnection.effectiveType;
- switch (effectiveType) {
- case 'slow-2g':
- return 1 /* EffectiveConnectionType.CONNECTION_SLOW_2G */;
- case '2g':
- return 2 /* EffectiveConnectionType.CONNECTION_2G */;
- case '3g':
- return 3 /* EffectiveConnectionType.CONNECTION_3G */;
- case '4g':
- return 4 /* EffectiveConnectionType.CONNECTION_4G */;
- default:
- return 0 /* EffectiveConnectionType.UNKNOWN */;
- }
- }
- function isValidCustomAttributeName(name) {
- if (name.length === 0 || name.length > MAX_ATTRIBUTE_NAME_LENGTH) {
- return false;
- }
- const matchesReservedPrefix = RESERVED_ATTRIBUTE_PREFIXES.some(prefix => name.startsWith(prefix));
- return !matchesReservedPrefix && !!name.match(ATTRIBUTE_FORMAT_REGEX);
- }
- function isValidCustomAttributeValue(value) {
- return value.length !== 0 && value.length <= MAX_ATTRIBUTE_VALUE_LENGTH;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function getAppId(firebaseApp) {
- var _a;
- const appId = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.appId;
- if (!appId) {
- throw ERROR_FACTORY.create("no app id" /* ErrorCode.NO_APP_ID */);
- }
- return appId;
- }
- function getProjectId(firebaseApp) {
- var _a;
- const projectId = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.projectId;
- if (!projectId) {
- throw ERROR_FACTORY.create("no project id" /* ErrorCode.NO_PROJECT_ID */);
- }
- return projectId;
- }
- function getApiKey(firebaseApp) {
- var _a;
- const apiKey = (_a = firebaseApp.options) === null || _a === void 0 ? void 0 : _a.apiKey;
- if (!apiKey) {
- throw ERROR_FACTORY.create("no api key" /* ErrorCode.NO_API_KEY */);
- }
- return apiKey;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const REMOTE_CONFIG_SDK_VERSION = '0.0.1';
- // These values will be used if the remote config object is successfully
- // retrieved, but the template does not have these fields.
- const DEFAULT_CONFIGS = {
- loggingEnabled: true
- };
- const FIS_AUTH_PREFIX = 'FIREBASE_INSTALLATIONS_AUTH';
- function getConfig(performanceController, iid) {
- const config = getStoredConfig();
- if (config) {
- processConfig(config);
- return Promise.resolve();
- }
- return getRemoteConfig(performanceController, iid)
- .then(processConfig)
- .then(config => storeConfig(config),
- /** Do nothing for error, use defaults set in settings service. */
- () => { });
- }
- function getStoredConfig() {
- const localStorage = Api.getInstance().localStorage;
- if (!localStorage) {
- return;
- }
- const expiryString = localStorage.getItem(CONFIG_EXPIRY_LOCAL_STORAGE_KEY);
- if (!expiryString || !configValid(expiryString)) {
- return;
- }
- const configStringified = localStorage.getItem(CONFIG_LOCAL_STORAGE_KEY);
- if (!configStringified) {
- return;
- }
- try {
- const configResponse = JSON.parse(configStringified);
- return configResponse;
- }
- catch (_a) {
- return;
- }
- }
- function storeConfig(config) {
- const localStorage = Api.getInstance().localStorage;
- if (!config || !localStorage) {
- return;
- }
- localStorage.setItem(CONFIG_LOCAL_STORAGE_KEY, JSON.stringify(config));
- localStorage.setItem(CONFIG_EXPIRY_LOCAL_STORAGE_KEY, String(Date.now() +
- SettingsService.getInstance().configTimeToLive * 60 * 60 * 1000));
- }
- const COULD_NOT_GET_CONFIG_MSG = 'Could not fetch config, will use default configs';
- function getRemoteConfig(performanceController, iid) {
- // Perf needs auth token only to retrieve remote config.
- return getAuthTokenPromise(performanceController.installations)
- .then(authToken => {
- const projectId = getProjectId(performanceController.app);
- const apiKey = getApiKey(performanceController.app);
- const configEndPoint = `https://firebaseremoteconfig.googleapis.com/v1/projects/${projectId}/namespaces/fireperf:fetch?key=${apiKey}`;
- const request = new Request(configEndPoint, {
- method: 'POST',
- headers: { Authorization: `${FIS_AUTH_PREFIX} ${authToken}` },
- /* eslint-disable camelcase */
- body: JSON.stringify({
- app_instance_id: iid,
- app_instance_id_token: authToken,
- app_id: getAppId(performanceController.app),
- app_version: SDK_VERSION,
- sdk_version: REMOTE_CONFIG_SDK_VERSION
- })
- /* eslint-enable camelcase */
- });
- return fetch(request).then(response => {
- if (response.ok) {
- return response.json();
- }
- // In case response is not ok. This will be caught by catch.
- throw ERROR_FACTORY.create("RC response not ok" /* ErrorCode.RC_NOT_OK */);
- });
- })
- .catch(() => {
- consoleLogger.info(COULD_NOT_GET_CONFIG_MSG);
- return undefined;
- });
- }
- /**
- * Processes config coming either from calling RC or from local storage.
- * This method only runs if call is successful or config in storage
- * is valid.
- */
- function processConfig(config) {
- if (!config) {
- return config;
- }
- const settingsServiceInstance = SettingsService.getInstance();
- const entries = config.entries || {};
- if (entries.fpr_enabled !== undefined) {
- // TODO: Change the assignment of loggingEnabled once the received type is
- // known.
- settingsServiceInstance.loggingEnabled =
- String(entries.fpr_enabled) === 'true';
- }
- else {
- // Config retrieved successfully, but there is no fpr_enabled in template.
- // Use secondary configs value.
- settingsServiceInstance.loggingEnabled = DEFAULT_CONFIGS.loggingEnabled;
- }
- if (entries.fpr_log_source) {
- settingsServiceInstance.logSource = Number(entries.fpr_log_source);
- }
- else if (DEFAULT_CONFIGS.logSource) {
- settingsServiceInstance.logSource = DEFAULT_CONFIGS.logSource;
- }
- if (entries.fpr_log_endpoint_url) {
- settingsServiceInstance.logEndPointUrl = entries.fpr_log_endpoint_url;
- }
- else if (DEFAULT_CONFIGS.logEndPointUrl) {
- settingsServiceInstance.logEndPointUrl = DEFAULT_CONFIGS.logEndPointUrl;
- }
- // Key from Remote Config has to be non-empty string, otherwsie use local value.
- if (entries.fpr_log_transport_key) {
- settingsServiceInstance.transportKey = entries.fpr_log_transport_key;
- }
- else if (DEFAULT_CONFIGS.transportKey) {
- settingsServiceInstance.transportKey = DEFAULT_CONFIGS.transportKey;
- }
- if (entries.fpr_vc_network_request_sampling_rate !== undefined) {
- settingsServiceInstance.networkRequestsSamplingRate = Number(entries.fpr_vc_network_request_sampling_rate);
- }
- else if (DEFAULT_CONFIGS.networkRequestsSamplingRate !== undefined) {
- settingsServiceInstance.networkRequestsSamplingRate =
- DEFAULT_CONFIGS.networkRequestsSamplingRate;
- }
- if (entries.fpr_vc_trace_sampling_rate !== undefined) {
- settingsServiceInstance.tracesSamplingRate = Number(entries.fpr_vc_trace_sampling_rate);
- }
- else if (DEFAULT_CONFIGS.tracesSamplingRate !== undefined) {
- settingsServiceInstance.tracesSamplingRate =
- DEFAULT_CONFIGS.tracesSamplingRate;
- }
- // Set the per session trace and network logging flags.
- settingsServiceInstance.logTraceAfterSampling = shouldLogAfterSampling(settingsServiceInstance.tracesSamplingRate);
- settingsServiceInstance.logNetworkAfterSampling = shouldLogAfterSampling(settingsServiceInstance.networkRequestsSamplingRate);
- return config;
- }
- function configValid(expiry) {
- return Number(expiry) > Date.now();
- }
- function shouldLogAfterSampling(samplingRate) {
- return Math.random() <= samplingRate;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- let initializationStatus = 1 /* InitializationStatus.notInitialized */;
- let initializationPromise;
- function getInitializationPromise(performanceController) {
- initializationStatus = 2 /* InitializationStatus.initializationPending */;
- initializationPromise =
- initializationPromise || initializePerf(performanceController);
- return initializationPromise;
- }
- function isPerfInitialized() {
- return initializationStatus === 3 /* InitializationStatus.initialized */;
- }
- function initializePerf(performanceController) {
- return getDocumentReadyComplete()
- .then(() => getIidPromise(performanceController.installations))
- .then(iid => getConfig(performanceController, iid))
- .then(() => changeInitializationStatus(), () => changeInitializationStatus());
- }
- /**
- * Returns a promise which resolves whenever the document readystate is complete or
- * immediately if it is called after page load complete.
- */
- function getDocumentReadyComplete() {
- const document = Api.getInstance().document;
- return new Promise(resolve => {
- if (document && document.readyState !== 'complete') {
- const handler = () => {
- if (document.readyState === 'complete') {
- document.removeEventListener('readystatechange', handler);
- resolve();
- }
- };
- document.addEventListener('readystatechange', handler);
- }
- else {
- resolve();
- }
- });
- }
- function changeInitializationStatus() {
- initializationStatus = 3 /* InitializationStatus.initialized */;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const DEFAULT_SEND_INTERVAL_MS = 10 * 1000;
- const INITIAL_SEND_TIME_DELAY_MS = 5.5 * 1000;
- // If end point does not work, the call will be tried for these many times.
- const DEFAULT_REMAINING_TRIES = 3;
- const MAX_EVENT_COUNT_PER_REQUEST = 1000;
- let remainingTries = DEFAULT_REMAINING_TRIES;
- /* eslint-enable camelcase */
- let queue = [];
- let isTransportSetup = false;
- function setupTransportService() {
- if (!isTransportSetup) {
- processQueue(INITIAL_SEND_TIME_DELAY_MS);
- isTransportSetup = true;
- }
- }
- function processQueue(timeOffset) {
- setTimeout(() => {
- // If there is no remainingTries left, stop retrying.
- if (remainingTries === 0) {
- return;
- }
- // If there are no events to process, wait for DEFAULT_SEND_INTERVAL_MS and try again.
- if (!queue.length) {
- return processQueue(DEFAULT_SEND_INTERVAL_MS);
- }
- dispatchQueueEvents();
- }, timeOffset);
- }
- function dispatchQueueEvents() {
- // Extract events up to the maximum cap of single logRequest from top of "official queue".
- // The staged events will be used for current logRequest attempt, remaining events will be kept
- // for next attempt.
- const staged = queue.splice(0, MAX_EVENT_COUNT_PER_REQUEST);
- /* eslint-disable camelcase */
- // We will pass the JSON serialized event to the backend.
- const log_event = staged.map(evt => ({
- source_extension_json_proto3: evt.message,
- event_time_ms: String(evt.eventTime)
- }));
- const data = {
- request_time_ms: String(Date.now()),
- client_info: {
- client_type: 1,
- js_client_info: {}
- },
- log_source: SettingsService.getInstance().logSource,
- log_event
- };
- /* eslint-enable camelcase */
- sendEventsToFl(data, staged).catch(() => {
- // If the request fails for some reason, add the events that were attempted
- // back to the primary queue to retry later.
- queue = [...staged, ...queue];
- remainingTries--;
- consoleLogger.info(`Tries left: ${remainingTries}.`);
- processQueue(DEFAULT_SEND_INTERVAL_MS);
- });
- }
- function sendEventsToFl(data, staged) {
- return postToFlEndpoint(data)
- .then(res => {
- if (!res.ok) {
- consoleLogger.info('Call to Firebase backend failed.');
- }
- return res.json();
- })
- .then(res => {
- // Find the next call wait time from the response.
- const transportWait = Number(res.nextRequestWaitMillis);
- let requestOffset = DEFAULT_SEND_INTERVAL_MS;
- if (!isNaN(transportWait)) {
- requestOffset = Math.max(transportWait, requestOffset);
- }
- // Delete request if response include RESPONSE_ACTION_UNKNOWN or DELETE_REQUEST action.
- // Otherwise, retry request using normal scheduling if response include RETRY_REQUEST_LATER.
- const logResponseDetails = res.logResponseDetails;
- if (Array.isArray(logResponseDetails) &&
- logResponseDetails.length > 0 &&
- logResponseDetails[0].responseAction === 'RETRY_REQUEST_LATER') {
- queue = [...staged, ...queue];
- consoleLogger.info(`Retry transport request later.`);
- }
- remainingTries = DEFAULT_REMAINING_TRIES;
- // Schedule the next process.
- processQueue(requestOffset);
- });
- }
- function postToFlEndpoint(data) {
- const flTransportFullUrl = SettingsService.getInstance().getFlTransportFullUrl();
- return fetch(flTransportFullUrl, {
- method: 'POST',
- body: JSON.stringify(data)
- });
- }
- function addToQueue(evt) {
- if (!evt.eventTime || !evt.message) {
- throw ERROR_FACTORY.create("invalid cc log" /* ErrorCode.INVALID_CC_LOG */);
- }
- // Add the new event to the queue.
- queue = [...queue, evt];
- }
- /** Log handler for cc service to send the performance logs to the server. */
- function transportHandler(
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- serializer) {
- return (...args) => {
- const message = serializer(...args);
- addToQueue({
- message,
- eventTime: Date.now()
- });
- };
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /* eslint-enble camelcase */
- let logger;
- // This method is not called before initialization.
- function sendLog(resource, resourceType) {
- if (!logger) {
- logger = transportHandler(serializer);
- }
- logger(resource, resourceType);
- }
- function logTrace(trace) {
- const settingsService = SettingsService.getInstance();
- // Do not log if trace is auto generated and instrumentation is disabled.
- if (!settingsService.instrumentationEnabled && trace.isAuto) {
- return;
- }
- // Do not log if trace is custom and data collection is disabled.
- if (!settingsService.dataCollectionEnabled && !trace.isAuto) {
- return;
- }
- // Do not log if required apis are not available.
- if (!Api.getInstance().requiredApisAvailable()) {
- return;
- }
- // Only log the page load auto traces if page is visible.
- if (trace.isAuto && getVisibilityState() !== VisibilityState.VISIBLE) {
- return;
- }
- if (isPerfInitialized()) {
- sendTraceLog(trace);
- }
- else {
- // Custom traces can be used before the initialization but logging
- // should wait until after.
- getInitializationPromise(trace.performanceController).then(() => sendTraceLog(trace), () => sendTraceLog(trace));
- }
- }
- function sendTraceLog(trace) {
- if (!getIid()) {
- return;
- }
- const settingsService = SettingsService.getInstance();
- if (!settingsService.loggingEnabled ||
- !settingsService.logTraceAfterSampling) {
- return;
- }
- setTimeout(() => sendLog(trace, 1 /* ResourceType.Trace */), 0);
- }
- function logNetworkRequest(networkRequest) {
- const settingsService = SettingsService.getInstance();
- // Do not log network requests if instrumentation is disabled.
- if (!settingsService.instrumentationEnabled) {
- return;
- }
- // Do not log the js sdk's call to transport service domain to avoid unnecessary cycle.
- // Need to blacklist both old and new endpoints to avoid migration gap.
- const networkRequestUrl = networkRequest.url;
- // Blacklist old log endpoint and new transport endpoint.
- // Because Performance SDK doesn't instrument requests sent from SDK itself.
- const logEndpointUrl = settingsService.logEndPointUrl.split('?')[0];
- const flEndpointUrl = settingsService.flTransportEndpointUrl.split('?')[0];
- if (networkRequestUrl === logEndpointUrl ||
- networkRequestUrl === flEndpointUrl) {
- return;
- }
- if (!settingsService.loggingEnabled ||
- !settingsService.logNetworkAfterSampling) {
- return;
- }
- setTimeout(() => sendLog(networkRequest, 0 /* ResourceType.NetworkRequest */), 0);
- }
- function serializer(resource, resourceType) {
- if (resourceType === 0 /* ResourceType.NetworkRequest */) {
- return serializeNetworkRequest(resource);
- }
- return serializeTrace(resource);
- }
- function serializeNetworkRequest(networkRequest) {
- const networkRequestMetric = {
- url: networkRequest.url,
- http_method: networkRequest.httpMethod || 0,
- http_response_code: 200,
- response_payload_bytes: networkRequest.responsePayloadBytes,
- client_start_time_us: networkRequest.startTimeUs,
- time_to_response_initiated_us: networkRequest.timeToResponseInitiatedUs,
- time_to_response_completed_us: networkRequest.timeToResponseCompletedUs
- };
- const perfMetric = {
- application_info: getApplicationInfo(networkRequest.performanceController.app),
- network_request_metric: networkRequestMetric
- };
- return JSON.stringify(perfMetric);
- }
- function serializeTrace(trace) {
- const traceMetric = {
- name: trace.name,
- is_auto: trace.isAuto,
- client_start_time_us: trace.startTimeUs,
- duration_us: trace.durationUs
- };
- if (Object.keys(trace.counters).length !== 0) {
- traceMetric.counters = trace.counters;
- }
- const customAttributes = trace.getAttributes();
- if (Object.keys(customAttributes).length !== 0) {
- traceMetric.custom_attributes = customAttributes;
- }
- const perfMetric = {
- application_info: getApplicationInfo(trace.performanceController.app),
- trace_metric: traceMetric
- };
- return JSON.stringify(perfMetric);
- }
- function getApplicationInfo(firebaseApp) {
- return {
- google_app_id: getAppId(firebaseApp),
- app_instance_id: getIid(),
- web_app_info: {
- sdk_version: SDK_VERSION,
- page_url: Api.getInstance().getUrl(),
- service_worker_status: getServiceWorkerStatus(),
- visibility_state: getVisibilityState(),
- effective_connection_type: getEffectiveConnectionType()
- },
- application_process_state: 0
- };
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const MAX_METRIC_NAME_LENGTH = 100;
- const RESERVED_AUTO_PREFIX = '_';
- const oobMetrics = [
- FIRST_PAINT_COUNTER_NAME,
- FIRST_CONTENTFUL_PAINT_COUNTER_NAME,
- FIRST_INPUT_DELAY_COUNTER_NAME
- ];
- /**
- * Returns true if the metric is custom and does not start with reserved prefix, or if
- * the metric is one of out of the box page load trace metrics.
- */
- function isValidMetricName(name, traceName) {
- if (name.length === 0 || name.length > MAX_METRIC_NAME_LENGTH) {
- return false;
- }
- return ((traceName &&
- traceName.startsWith(OOB_TRACE_PAGE_LOAD_PREFIX) &&
- oobMetrics.indexOf(name) > -1) ||
- !name.startsWith(RESERVED_AUTO_PREFIX));
- }
- /**
- * Converts the provided value to an integer value to be used in case of a metric.
- * @param providedValue Provided number value of the metric that needs to be converted to an integer.
- *
- * @returns Converted integer number to be set for the metric.
- */
- function convertMetricValueToInteger(providedValue) {
- const valueAsInteger = Math.floor(providedValue);
- if (valueAsInteger < providedValue) {
- consoleLogger.info(`Metric value should be an Integer, setting the value as : ${valueAsInteger}.`);
- }
- return valueAsInteger;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class Trace {
- /**
- * @param performanceController The performance controller running.
- * @param name The name of the trace.
- * @param isAuto If the trace is auto-instrumented.
- * @param traceMeasureName The name of the measure marker in user timing specification. This field
- * is only set when the trace is built for logging when the user directly uses the user timing
- * api (performance.mark and performance.measure).
- */
- constructor(performanceController, name, isAuto = false, traceMeasureName) {
- this.performanceController = performanceController;
- this.name = name;
- this.isAuto = isAuto;
- this.state = 1 /* TraceState.UNINITIALIZED */;
- this.customAttributes = {};
- this.counters = {};
- this.api = Api.getInstance();
- this.randomId = Math.floor(Math.random() * 1000000);
- if (!this.isAuto) {
- this.traceStartMark = `${TRACE_START_MARK_PREFIX}-${this.randomId}-${this.name}`;
- this.traceStopMark = `${TRACE_STOP_MARK_PREFIX}-${this.randomId}-${this.name}`;
- this.traceMeasure =
- traceMeasureName ||
- `${TRACE_MEASURE_PREFIX}-${this.randomId}-${this.name}`;
- if (traceMeasureName) {
- // For the case of direct user timing traces, no start stop will happen. The measure object
- // is already available.
- this.calculateTraceMetrics();
- }
- }
- }
- /**
- * Starts a trace. The measurement of the duration starts at this point.
- */
- start() {
- if (this.state !== 1 /* TraceState.UNINITIALIZED */) {
- throw ERROR_FACTORY.create("trace started" /* ErrorCode.TRACE_STARTED_BEFORE */, {
- traceName: this.name
- });
- }
- this.api.mark(this.traceStartMark);
- this.state = 2 /* TraceState.RUNNING */;
- }
- /**
- * Stops the trace. The measurement of the duration of the trace stops at this point and trace
- * is logged.
- */
- stop() {
- if (this.state !== 2 /* TraceState.RUNNING */) {
- throw ERROR_FACTORY.create("trace stopped" /* ErrorCode.TRACE_STOPPED_BEFORE */, {
- traceName: this.name
- });
- }
- this.state = 3 /* TraceState.TERMINATED */;
- this.api.mark(this.traceStopMark);
- this.api.measure(this.traceMeasure, this.traceStartMark, this.traceStopMark);
- this.calculateTraceMetrics();
- logTrace(this);
- }
- /**
- * Records a trace with predetermined values. If this method is used a trace is created and logged
- * directly. No need to use start and stop methods.
- * @param startTime Trace start time since epoch in millisec
- * @param duration The duraction of the trace in millisec
- * @param options An object which can optionally hold maps of custom metrics and custom attributes
- */
- record(startTime, duration, options) {
- if (startTime <= 0) {
- throw ERROR_FACTORY.create("nonpositive trace startTime" /* ErrorCode.NONPOSITIVE_TRACE_START_TIME */, {
- traceName: this.name
- });
- }
- if (duration <= 0) {
- throw ERROR_FACTORY.create("nonpositive trace duration" /* ErrorCode.NONPOSITIVE_TRACE_DURATION */, {
- traceName: this.name
- });
- }
- this.durationUs = Math.floor(duration * 1000);
- this.startTimeUs = Math.floor(startTime * 1000);
- if (options && options.attributes) {
- this.customAttributes = Object.assign({}, options.attributes);
- }
- if (options && options.metrics) {
- for (const metricName of Object.keys(options.metrics)) {
- if (!isNaN(Number(options.metrics[metricName]))) {
- this.counters[metricName] = Math.floor(Number(options.metrics[metricName]));
- }
- }
- }
- logTrace(this);
- }
- /**
- * Increments a custom metric by a certain number or 1 if number not specified. Will create a new
- * custom metric if one with the given name does not exist. The value will be floored down to an
- * integer.
- * @param counter Name of the custom metric
- * @param numAsInteger Increment by value
- */
- incrementMetric(counter, numAsInteger = 1) {
- if (this.counters[counter] === undefined) {
- this.putMetric(counter, numAsInteger);
- }
- else {
- this.putMetric(counter, this.counters[counter] + numAsInteger);
- }
- }
- /**
- * Sets a custom metric to a specified value. Will create a new custom metric if one with the
- * given name does not exist. The value will be floored down to an integer.
- * @param counter Name of the custom metric
- * @param numAsInteger Set custom metric to this value
- */
- putMetric(counter, numAsInteger) {
- if (isValidMetricName(counter, this.name)) {
- this.counters[counter] = convertMetricValueToInteger(numAsInteger !== null && numAsInteger !== void 0 ? numAsInteger : 0);
- }
- else {
- throw ERROR_FACTORY.create("invalid custom metric name" /* ErrorCode.INVALID_CUSTOM_METRIC_NAME */, {
- customMetricName: counter
- });
- }
- }
- /**
- * Returns the value of the custom metric by that name. If a custom metric with that name does
- * not exist will return zero.
- * @param counter
- */
- getMetric(counter) {
- return this.counters[counter] || 0;
- }
- /**
- * Sets a custom attribute of a trace to a certain value.
- * @param attr
- * @param value
- */
- putAttribute(attr, value) {
- const isValidName = isValidCustomAttributeName(attr);
- const isValidValue = isValidCustomAttributeValue(value);
- if (isValidName && isValidValue) {
- this.customAttributes[attr] = value;
- return;
- }
- // Throw appropriate error when the attribute name or value is invalid.
- if (!isValidName) {
- throw ERROR_FACTORY.create("invalid attribute name" /* ErrorCode.INVALID_ATTRIBUTE_NAME */, {
- attributeName: attr
- });
- }
- if (!isValidValue) {
- throw ERROR_FACTORY.create("invalid attribute value" /* ErrorCode.INVALID_ATTRIBUTE_VALUE */, {
- attributeValue: value
- });
- }
- }
- /**
- * Retrieves the value a custom attribute of a trace is set to.
- * @param attr
- */
- getAttribute(attr) {
- return this.customAttributes[attr];
- }
- removeAttribute(attr) {
- if (this.customAttributes[attr] === undefined) {
- return;
- }
- delete this.customAttributes[attr];
- }
- getAttributes() {
- return Object.assign({}, this.customAttributes);
- }
- setStartTime(startTime) {
- this.startTimeUs = startTime;
- }
- setDuration(duration) {
- this.durationUs = duration;
- }
- /**
- * Calculates and assigns the duration and start time of the trace using the measure performance
- * entry.
- */
- calculateTraceMetrics() {
- const perfMeasureEntries = this.api.getEntriesByName(this.traceMeasure);
- const perfMeasureEntry = perfMeasureEntries && perfMeasureEntries[0];
- if (perfMeasureEntry) {
- this.durationUs = Math.floor(perfMeasureEntry.duration * 1000);
- this.startTimeUs = Math.floor((perfMeasureEntry.startTime + this.api.getTimeOrigin()) * 1000);
- }
- }
- /**
- * @param navigationTimings A single element array which contains the navigationTIming object of
- * the page load
- * @param paintTimings A array which contains paintTiming object of the page load
- * @param firstInputDelay First input delay in millisec
- */
- static createOobTrace(performanceController, navigationTimings, paintTimings, firstInputDelay) {
- const route = Api.getInstance().getUrl();
- if (!route) {
- return;
- }
- const trace = new Trace(performanceController, OOB_TRACE_PAGE_LOAD_PREFIX + route, true);
- const timeOriginUs = Math.floor(Api.getInstance().getTimeOrigin() * 1000);
- trace.setStartTime(timeOriginUs);
- // navigationTimings includes only one element.
- if (navigationTimings && navigationTimings[0]) {
- trace.setDuration(Math.floor(navigationTimings[0].duration * 1000));
- trace.putMetric('domInteractive', Math.floor(navigationTimings[0].domInteractive * 1000));
- trace.putMetric('domContentLoadedEventEnd', Math.floor(navigationTimings[0].domContentLoadedEventEnd * 1000));
- trace.putMetric('loadEventEnd', Math.floor(navigationTimings[0].loadEventEnd * 1000));
- }
- const FIRST_PAINT = 'first-paint';
- const FIRST_CONTENTFUL_PAINT = 'first-contentful-paint';
- if (paintTimings) {
- const firstPaint = paintTimings.find(paintObject => paintObject.name === FIRST_PAINT);
- if (firstPaint && firstPaint.startTime) {
- trace.putMetric(FIRST_PAINT_COUNTER_NAME, Math.floor(firstPaint.startTime * 1000));
- }
- const firstContentfulPaint = paintTimings.find(paintObject => paintObject.name === FIRST_CONTENTFUL_PAINT);
- if (firstContentfulPaint && firstContentfulPaint.startTime) {
- trace.putMetric(FIRST_CONTENTFUL_PAINT_COUNTER_NAME, Math.floor(firstContentfulPaint.startTime * 1000));
- }
- if (firstInputDelay) {
- trace.putMetric(FIRST_INPUT_DELAY_COUNTER_NAME, Math.floor(firstInputDelay * 1000));
- }
- }
- logTrace(trace);
- }
- static createUserTimingTrace(performanceController, measureName) {
- const trace = new Trace(performanceController, measureName, false, measureName);
- logTrace(trace);
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function createNetworkRequestEntry(performanceController, entry) {
- const performanceEntry = entry;
- if (!performanceEntry || performanceEntry.responseStart === undefined) {
- return;
- }
- const timeOrigin = Api.getInstance().getTimeOrigin();
- const startTimeUs = Math.floor((performanceEntry.startTime + timeOrigin) * 1000);
- const timeToResponseInitiatedUs = performanceEntry.responseStart
- ? Math.floor((performanceEntry.responseStart - performanceEntry.startTime) * 1000)
- : undefined;
- const timeToResponseCompletedUs = Math.floor((performanceEntry.responseEnd - performanceEntry.startTime) * 1000);
- // Remove the query params from logged network request url.
- const url = performanceEntry.name && performanceEntry.name.split('?')[0];
- const networkRequest = {
- performanceController,
- url,
- responsePayloadBytes: performanceEntry.transferSize,
- startTimeUs,
- timeToResponseInitiatedUs,
- timeToResponseCompletedUs
- };
- logNetworkRequest(networkRequest);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const FID_WAIT_TIME_MS = 5000;
- function setupOobResources(performanceController) {
- // Do not initialize unless iid is available.
- if (!getIid()) {
- return;
- }
- // The load event might not have fired yet, and that means performance navigation timing
- // object has a duration of 0. The setup should run after all current tasks in js queue.
- setTimeout(() => setupOobTraces(performanceController), 0);
- setTimeout(() => setupNetworkRequests(performanceController), 0);
- setTimeout(() => setupUserTimingTraces(performanceController), 0);
- }
- function setupNetworkRequests(performanceController) {
- const api = Api.getInstance();
- const resources = api.getEntriesByType('resource');
- for (const resource of resources) {
- createNetworkRequestEntry(performanceController, resource);
- }
- api.setupObserver('resource', entry => createNetworkRequestEntry(performanceController, entry));
- }
- function setupOobTraces(performanceController) {
- const api = Api.getInstance();
- const navigationTimings = api.getEntriesByType('navigation');
- const paintTimings = api.getEntriesByType('paint');
- // If First Input Desly polyfill is added to the page, report the fid value.
- // https://github.com/GoogleChromeLabs/first-input-delay
- if (api.onFirstInputDelay) {
- // If the fid call back is not called for certain time, continue without it.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- let timeoutId = setTimeout(() => {
- Trace.createOobTrace(performanceController, navigationTimings, paintTimings);
- timeoutId = undefined;
- }, FID_WAIT_TIME_MS);
- api.onFirstInputDelay((fid) => {
- if (timeoutId) {
- clearTimeout(timeoutId);
- Trace.createOobTrace(performanceController, navigationTimings, paintTimings, fid);
- }
- });
- }
- else {
- Trace.createOobTrace(performanceController, navigationTimings, paintTimings);
- }
- }
- function setupUserTimingTraces(performanceController) {
- const api = Api.getInstance();
- // Run through the measure performance entries collected up to this point.
- const measures = api.getEntriesByType('measure');
- for (const measure of measures) {
- createUserTimingTrace(performanceController, measure);
- }
- // Setup an observer to capture the measures from this point on.
- api.setupObserver('measure', entry => createUserTimingTrace(performanceController, entry));
- }
- function createUserTimingTrace(performanceController, measure) {
- const measureName = measure.name;
- // Do not create a trace, if the user timing marks and measures are created by the sdk itself.
- if (measureName.substring(0, TRACE_MEASURE_PREFIX.length) ===
- TRACE_MEASURE_PREFIX) {
- return;
- }
- Trace.createUserTimingTrace(performanceController, measureName);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class PerformanceController {
- constructor(app, installations) {
- this.app = app;
- this.installations = installations;
- this.initialized = false;
- }
- /**
- * This method *must* be called internally as part of creating a
- * PerformanceController instance.
- *
- * Currently it's not possible to pass the settings object through the
- * constructor using Components, so this method exists to be called with the
- * desired settings, to ensure nothing is collected without the user's
- * consent.
- */
- _init(settings) {
- if (this.initialized) {
- return;
- }
- if ((settings === null || settings === void 0 ? void 0 : settings.dataCollectionEnabled) !== undefined) {
- this.dataCollectionEnabled = settings.dataCollectionEnabled;
- }
- if ((settings === null || settings === void 0 ? void 0 : settings.instrumentationEnabled) !== undefined) {
- this.instrumentationEnabled = settings.instrumentationEnabled;
- }
- if (Api.getInstance().requiredApisAvailable()) {
- validateIndexedDBOpenable()
- .then(isAvailable => {
- if (isAvailable) {
- setupTransportService();
- getInitializationPromise(this).then(() => setupOobResources(this), () => setupOobResources(this));
- this.initialized = true;
- }
- })
- .catch(error => {
- consoleLogger.info(`Environment doesn't support IndexedDB: ${error}`);
- });
- }
- else {
- consoleLogger.info('Firebase Performance cannot start if the browser does not support ' +
- '"Fetch" and "Promise", or cookies are disabled.');
- }
- }
- set instrumentationEnabled(val) {
- SettingsService.getInstance().instrumentationEnabled = val;
- }
- get instrumentationEnabled() {
- return SettingsService.getInstance().instrumentationEnabled;
- }
- set dataCollectionEnabled(val) {
- SettingsService.getInstance().dataCollectionEnabled = val;
- }
- get dataCollectionEnabled() {
- return SettingsService.getInstance().dataCollectionEnabled;
- }
- }
-
- /**
- * Firebase Performance Monitoring
- *
- * @packageDocumentation
- */
- const DEFAULT_ENTRY_NAME = '[DEFAULT]';
- /**
- * Returns a new `PerformanceTrace` instance.
- * @param performance - The {@link FirebasePerformance} instance to use.
- * @param name - The name of the trace.
- * @public
- */
- function trace(performance, name) {
- performance = getModularInstance(performance);
- return new Trace(performance, name);
- }
- const factory = (container, { options: settings }) => {
- // Dependencies
- const app = container.getProvider('app').getImmediate();
- const installations = container
- .getProvider('installations-internal')
- .getImmediate();
- if (app.name !== DEFAULT_ENTRY_NAME) {
- throw ERROR_FACTORY.create("FB not default" /* ErrorCode.FB_NOT_DEFAULT */);
- }
- if (typeof window === 'undefined') {
- throw ERROR_FACTORY.create("no window" /* ErrorCode.NO_WINDOW */);
- }
- setupApi(window);
- const perfInstance = new PerformanceController(app, installations);
- perfInstance._init(settings);
- return perfInstance;
- };
- function registerPerformance() {
- _registerComponent(new Component('performance', factory, "PUBLIC" /* ComponentType.PUBLIC */));
- registerVersion(name$4, version$4);
- // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
- registerVersion(name$4, version$4, 'esm2017');
- }
- registerPerformance();
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class PerformanceCompatImpl {
- constructor(app, _delegate) {
- this.app = app;
- this._delegate = _delegate;
- }
- get instrumentationEnabled() {
- return this._delegate.instrumentationEnabled;
- }
- set instrumentationEnabled(val) {
- this._delegate.instrumentationEnabled = val;
- }
- get dataCollectionEnabled() {
- return this._delegate.dataCollectionEnabled;
- }
- set dataCollectionEnabled(val) {
- this._delegate.dataCollectionEnabled = val;
- }
- trace(traceName) {
- return trace(this._delegate, traceName);
- }
- }
-
- const name$3 = "@firebase/performance-compat";
- const version$3 = "0.2.4";
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function registerPerformanceCompat(firebaseInstance) {
- firebaseInstance.INTERNAL.registerComponent(new Component('performance-compat', performanceFactory, "PUBLIC" /* ComponentType.PUBLIC */));
- firebaseInstance.registerVersion(name$3, version$3);
- }
- function performanceFactory(container) {
- const app = container.getProvider('app-compat').getImmediate();
- // The following call will always succeed.
- const performance = container.getProvider('performance').getImmediate();
- return new PerformanceCompatImpl(app, performance);
- }
- registerPerformanceCompat(firebase);
-
- /* src/components/misccomponents/Spinner.svelte generated by Svelte v3.59.1 */
-
- const file$V = "src/components/misccomponents/Spinner.svelte";
-
- function create_fragment$X(ctx) {
- let div7;
- let div6;
- let div5;
- let div4;
- let div3;
- let div0;
- let svg0;
- let circle;
- let t0;
- let div1;
- let svg1;
- let polygon;
- let t1;
- let div2;
- let svg2;
- let rect;
-
- const block = {
- c: function create() {
- div7 = element("div");
- div6 = element("div");
- div5 = element("div");
- div4 = element("div");
- div3 = element("div");
- div0 = element("div");
- svg0 = svg_element("svg");
- circle = svg_element("circle");
- t0 = space();
- div1 = element("div");
- svg1 = svg_element("svg");
- polygon = svg_element("polygon");
- t1 = space();
- div2 = element("div");
- svg2 = svg_element("svg");
- rect = svg_element("rect");
- attr_dev(circle, "id", "test");
- attr_dev(circle, "cx", "40");
- attr_dev(circle, "cy", "40");
- attr_dev(circle, "r", "32");
- attr_dev(circle, "class", "svelte-o03b1q");
- add_location(circle, file$V, 128, 14, 3140);
- attr_dev(svg0, "viewBox", "0 0 80 80");
- attr_dev(svg0, "class", "svelte-o03b1q");
- add_location(svg0, file$V, 127, 12, 3100);
- attr_dev(div0, "class", "loader svelte-o03b1q");
- add_location(div0, file$V, 126, 10, 3067);
- attr_dev(polygon, "points", "43 8 79 72 7 72");
- attr_dev(polygon, "class", "svelte-o03b1q");
- add_location(polygon, file$V, 134, 14, 3313);
- attr_dev(svg1, "viewBox", "0 0 86 80");
- attr_dev(svg1, "class", "svelte-o03b1q");
- add_location(svg1, file$V, 133, 12, 3273);
- attr_dev(div1, "class", "loader triangle svelte-o03b1q");
- add_location(div1, file$V, 132, 10, 3231);
- attr_dev(rect, "x", "8");
- attr_dev(rect, "y", "8");
- attr_dev(rect, "width", "64");
- attr_dev(rect, "height", "64");
- attr_dev(rect, "class", "svelte-o03b1q");
- add_location(rect, file$V, 140, 14, 3470);
- attr_dev(svg2, "viewBox", "0 0 80 80");
- attr_dev(svg2, "class", "svelte-o03b1q");
- add_location(svg2, file$V, 139, 12, 3430);
- attr_dev(div2, "class", "loader svelte-o03b1q");
- add_location(div2, file$V, 138, 10, 3397);
- attr_dev(div3, "class", "lead m-auto text-center apploader pt-2 svelte-o03b1q");
- add_location(div3, file$V, 125, 8, 3004);
- attr_dev(div4, "class", "text-center svelte-o03b1q");
- add_location(div4, file$V, 124, 6, 2970);
- attr_dev(div5, "class", "mx-auto svelte-o03b1q");
- add_location(div5, file$V, 123, 4, 2942);
- attr_dev(div6, "class", "row align-items-center h-100 svelte-o03b1q");
- add_location(div6, file$V, 122, 2, 2895);
- attr_dev(div7, "class", "container h-100 svelte-o03b1q");
- add_location(div7, file$V, 121, 0, 2863);
- },
- l: function claim(nodes) {
- throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
- },
- m: function mount(target, anchor) {
- insert_dev(target, div7, anchor);
- append_dev(div7, div6);
- append_dev(div6, div5);
- append_dev(div5, div4);
- append_dev(div4, div3);
- append_dev(div3, div0);
- append_dev(div0, svg0);
- append_dev(svg0, circle);
- append_dev(div3, t0);
- append_dev(div3, div1);
- append_dev(div1, svg1);
- append_dev(svg1, polygon);
- append_dev(div3, t1);
- append_dev(div3, div2);
- append_dev(div2, svg2);
- append_dev(svg2, rect);
- },
- p: noop$1,
- i: noop$1,
- o: noop$1,
- d: function destroy(detaching) {
- if (detaching) detach_dev(div7);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_fragment$X.name,
- type: "component",
- source: "",
- ctx
- });
-
- return block;
- }
-
- function instance$X($$self, $$props) {
- let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots('Spinner', slots, []);
- const writable_props = [];
-
- Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
- });
-
- return [];
- }
-
- class Spinner extends SvelteComponentDev {
- constructor(options) {
- super(options);
- init(this, options, instance$X, create_fragment$X, safe_not_equal, {});
-
- dispatch_dev("SvelteRegisterComponent", {
- component: this,
- tagName: "Spinner",
- options,
- id: create_fragment$X.name
- });
- }
- }
-
- const subscriber_queue = [];
- /**
- * Creates a `Readable` store that allows reading by subscription.
- * @param value initial value
- * @param {StartStopNotifier} [start]
- */
- function readable(value, start) {
- return {
- subscribe: writable$1(value, start).subscribe
- };
- }
- /**
- * Create a `Writable` store that allows both updating and reading by subscription.
- * @param {*=}value initial value
- * @param {StartStopNotifier=} start
- */
- function writable$1(value, start = noop$1) {
- let stop;
- const subscribers = new Set();
- function set(new_value) {
- if (safe_not_equal(value, new_value)) {
- value = new_value;
- if (stop) { // store is ready
- const run_queue = !subscriber_queue.length;
- for (const subscriber of subscribers) {
- subscriber[1]();
- subscriber_queue.push(subscriber, value);
- }
- if (run_queue) {
- for (let i = 0; i < subscriber_queue.length; i += 2) {
- subscriber_queue[i][0](subscriber_queue[i + 1]);
- }
- subscriber_queue.length = 0;
- }
- }
- }
- }
- function update(fn) {
- set(fn(value));
- }
- function subscribe(run, invalidate = noop$1) {
- const subscriber = [run, invalidate];
- subscribers.add(subscriber);
- if (subscribers.size === 1) {
- stop = start(set) || noop$1;
- }
- run(value);
- return () => {
- subscribers.delete(subscriber);
- if (subscribers.size === 0 && stop) {
- stop();
- stop = null;
- }
- };
- }
- return { set, update, subscribe };
- }
- function derived(stores, fn, initial_value) {
- const single = !Array.isArray(stores);
- const stores_array = single
- ? [stores]
- : stores;
- const auto = fn.length < 2;
- return readable(initial_value, (set) => {
- let started = false;
- const values = [];
- let pending = 0;
- let cleanup = noop$1;
- const sync = () => {
- if (pending) {
- return;
- }
- cleanup();
- const result = fn(single ? values[0] : values, set);
- if (auto) {
- set(result);
- }
- else {
- cleanup = is_function(result) ? result : noop$1;
- }
- };
- const unsubscribers = stores_array.map((store, i) => subscribe(store, (value) => {
- values[i] = value;
- pending &= ~(1 << i);
- if (started) {
- sync();
- }
- }, () => {
- pending |= (1 << i);
- }));
- started = true;
- sync();
- return function stop() {
- run_all(unsubscribers);
- cleanup();
- // We need to set this to false because callbacks can still happen despite having unsubscribed:
- // Callbacks might already be placed in the queue which doesn't know it should no longer
- // invoke this derived store.
- started = false;
- };
- });
- }
- /**
- * Takes a store and returns a new one derived from the old one that is readable.
- *
- * @param store - store to make readonly
- */
- function readonly(store) {
- return {
- subscribe: store.subscribe.bind(store)
- };
- }
-
- var store$1 = /*#__PURE__*/Object.freeze({
- __proto__: null,
- derived: derived,
- readable: readable,
- readonly: readonly,
- writable: writable$1,
- get: get_store_value
- });
-
- var commonjsGlobal$1 = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
-
- function unwrapExports (x) {
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
- }
-
- function createCommonjsModule(fn, module) {
- return module = { exports: {} }, fn(module, module.exports), module.exports;
- }
-
- function getCjsExportFromNamespace (n) {
- return n && n['default'] || n;
- }
-
- var require$$0 = getCjsExportFromNamespace(store$1);
-
- const writable = require$$0.writable;
-
- const router$1 = writable({});
-
- function set(route) {
- router$1.set(route);
- }
-
- function remove() {
- router$1.set({});
- }
-
- const activeRoute$1 = {
- subscribe: router$1.subscribe,
- set,
- remove
- };
-
- var store = { activeRoute: activeRoute$1 };
- var store_1 = store.activeRoute;
-
- const UrlParser$4 = (urlString, namedUrl = "") => {
- const urlBase = new URL(urlString);
-
- /**
- * Wrapper for URL.hash
- *
- **/
- function hash() {
- return urlBase.hash;
- }
-
- /**
- * Wrapper for URL.host
- *
- **/
- function host() {
- return urlBase.host;
- }
-
- /**
- * Wrapper for URL.hostname
- *
- **/
- function hostname() {
- return urlBase.hostname;
- }
-
- /**
- * Returns an object with all the named params and their values
- *
- **/
- function namedParams() {
- const allPathName = pathNames();
- const allNamedParamsKeys = namedParamsWithIndex();
-
- return allNamedParamsKeys.reduce((values, paramKey) => {
- values[paramKey.value] = allPathName[paramKey.index];
- return values;
- }, {});
- }
-
- /**
- * Returns an array with all the named param keys
- *
- **/
- function namedParamsKeys() {
- const allNamedParamsKeys = namedParamsWithIndex();
-
- return allNamedParamsKeys.reduce((values, paramKey) => {
- values.push(paramKey.value);
- return values;
- }, []);
- }
-
- /**
- * Returns an array with all the named param values
- *
- **/
- function namedParamsValues() {
- const allPathName = pathNames();
- const allNamedParamsKeys = namedParamsWithIndex();
-
- return allNamedParamsKeys.reduce((values, paramKey) => {
- values.push(allPathName[paramKey.index]);
- return values;
- }, []);
- }
-
- /**
- * Returns an array with all named param ids and their position in the path
- * Private
- **/
- function namedParamsWithIndex() {
- const namedUrlParams = getPathNames(namedUrl);
-
- return namedUrlParams.reduce((validParams, param, index) => {
- if (param[0] === ":") {
- validParams.push({ value: param.slice(1), index });
- }
- return validParams;
- }, []);
- }
-
- /**
- * Wrapper for URL.port
- *
- **/
- function port() {
- return urlBase.port;
- }
-
- /**
- * Wrapper for URL.pathname
- *
- **/
- function pathname() {
- return urlBase.pathname;
- }
-
- /**
- * Wrapper for URL.protocol
- *
- **/
- function protocol() {
- return urlBase.protocol;
- }
-
- /**
- * Wrapper for URL.search
- *
- **/
- function search() {
- return urlBase.search;
- }
-
- /**
- * Returns an object with all query params and their values
- *
- **/
- function queryParams() {
- const params = {};
- urlBase.searchParams.forEach((value, key) => {
- params[key] = value;
- });
-
- return params;
- }
-
- /**
- * Returns an array with all the query param keys
- *
- **/
- function queryParamsKeys() {
- const params = [];
- urlBase.searchParams.forEach((_value, key) => {
- params.push(key);
- });
-
- return params;
- }
-
- /**
- * Returns an array with all the query param values
- *
- **/
- function queryParamsValues() {
- const params = [];
- urlBase.searchParams.forEach((value) => {
- params.push(value);
- });
-
- return params;
- }
-
- /**
- * Returns an array with all the elements of a pathname
- *
- **/
- function pathNames() {
- return getPathNames(urlBase.pathname);
- }
-
- /**
- * Returns an array with all the parts of a pathname
- * Private method
- **/
- function getPathNames(pathName) {
- if (pathName === "/" || pathName.trim().length === 0) return [pathName];
- if (pathName.slice(-1) === "/") {
- pathName = pathName.slice(0, -1);
- }
- if (pathName[0] === "/") {
- pathName = pathName.slice(1);
- }
-
- return pathName.split("/");
- }
-
- return Object.freeze({
- hash: hash(),
- host: host(),
- hostname: hostname(),
- namedParams: namedParams(),
- namedParamsKeys: namedParamsKeys(),
- namedParamsValues: namedParamsValues(),
- pathNames: pathNames(),
- port: port(),
- pathname: pathname(),
- protocol: protocol(),
- search: search(),
- queryParams: queryParams(),
- queryParamsKeys: queryParamsKeys(),
- queryParamsValues: queryParamsValues(),
- });
- };
-
- var url_parser = { UrlParser: UrlParser$4 };
-
- const UrlParser$3 = url_parser.UrlParser;
-
- var urlParamsParser = {
- UrlParser: UrlParser$3
- };
-
- /**
- * Returns true if object has any nested routes empty
- * @param routeObject
- **/
- function anyEmptyNestedRoutes$1(routeObject) {
- let result = false;
- if (Object.keys(routeObject).length === 0) {
- return true
- }
-
- if (routeObject.childRoute && Object.keys(routeObject.childRoute).length === 0) {
- result = true;
- } else if (routeObject.childRoute) {
- result = anyEmptyNestedRoutes$1(routeObject.childRoute);
- }
-
- return result
- }
-
- /**
- * Compare two routes ignoring named params
- * @param pathName string
- * @param routeName string
- **/
-
- function compareRoutes(pathName, routeName) {
- routeName = removeSlash$2(routeName);
-
- if (routeName.includes(':')) {
- return routeName.includes(pathName)
- } else {
- return routeName.startsWith(pathName)
- }
- }
-
- /**
- * Returns a boolean indicating if the name of path exists in the route based on the language parameter
- * @param pathName string
- * @param route object
- * @param language string
- **/
-
- function findLocalisedRoute(pathName, route, language) {
- let exists = false;
-
- if (language) {
- return { exists: route.lang && route.lang[language] && route.lang[language].includes(pathName), language }
- }
-
- exists = compareRoutes(pathName, route.name);
-
- if (!exists && route.lang && typeof route.lang === 'object') {
- for (const [key, value] of Object.entries(route.lang)) {
- if (compareRoutes(pathName, value)) {
- exists = true;
- language = key;
- }
- }
- }
-
- return { exists, language }
- }
-
- /**
- * Return all the consecutive named param (placeholders) of a pathname
- * @param pathname
- **/
- function getNamedParams$1(pathName = '') {
- if (pathName.trim().length === 0) return []
- const namedUrlParams = getPathNames(pathName);
- return namedUrlParams.reduce((validParams, param) => {
- if (param[0] === ':') {
- validParams.push(param.slice(1));
- }
-
- return validParams
- }, [])
- }
-
- /**
- * Split a pathname based on /
- * @param pathName
- * Private method
- **/
- function getPathNames(pathName) {
- if (pathName === '/' || pathName.trim().length === 0) return [pathName]
-
- pathName = removeSlash$2(pathName, 'both');
-
- return pathName.split('/')
- }
-
- /**
- * Return the first part of a pathname until the first named param is found
- * @param name
- **/
- function nameToPath$1(name = '') {
- let routeName;
- if (name === '/' || name.trim().length === 0) return name
- name = removeSlash$2(name, 'lead');
- routeName = name.split(':')[0];
- routeName = removeSlash$2(routeName, 'trail');
-
- return routeName.toLowerCase()
- }
-
- /**
- * Return the path name excluding query params
- * @param name
- **/
- function pathWithoutQueryParams$1(currentRoute) {
- const path = currentRoute.path.split('?');
- return path[0]
- }
-
- /**
- * Return the path name including query params
- * @param name
- **/
- function pathWithQueryParams$1(currentRoute) {
- let queryParams = [];
- if (currentRoute.queryParams) {
- for (let [key, value] of Object.entries(currentRoute.queryParams)) {
- queryParams.push(`${key}=${value}`);
- }
- }
-
- const hash = currentRoute.hash ? currentRoute.hash : '';
-
- if (queryParams.length > 0) {
- return `${currentRoute.path}?${queryParams.join('&')}${hash}`
- } else {
- return currentRoute.path + hash
- }
- }
-
- /**
- * Returns a string with trailing or leading slash character removed
- * @param pathName string
- * @param position string - lead, trail, both
- **/
- function removeExtraPaths$1(pathNames, basePathNames) {
- const names = basePathNames.split('/');
- if (names.length > 1) {
- names.forEach(function (name, index) {
- if (name.length > 0 && index > 0) {
- pathNames.shift();
- }
- });
- }
-
- return pathNames
- }
-
- /**
- * Returns a string with trailing or leading slash character removed
- * @param pathName string
- * @param position string - lead, trail, both
- **/
-
- function removeSlash$2(pathName, position = 'lead') {
- if (pathName.trim().length < 1) {
- return ''
- }
-
- if (position === 'trail' || position === 'both') {
- if (pathName.slice(-1) === '/') {
- pathName = pathName.slice(0, -1);
- }
- }
-
- if (position === 'lead' || position === 'both') {
- if (pathName[0] === '/') {
- pathName = pathName.slice(1);
- }
- }
-
- return pathName
- }
-
- /**
- * Returns the name of the route based on the language parameter
- * @param route object
- * @param language string
- **/
-
- function routeNameLocalised$1(route, language = null) {
- if (!language || !route.lang || !route.lang[language]) {
- return route.name
- } else {
- return route.lang[language]
- }
- }
-
- /**
- * Return the path name excluding query params
- * @param name
- **/
- function startsWithNamedParam$1(currentRoute) {
- const routeName = removeSlash$2(currentRoute);
- return routeName.startsWith(':')
- }
-
- /**
- * Updates the base route path.
- * Route objects can have nested routes (childRoutes) or just a long name like "admin/employees/show/:id"
- *
- * @param basePath string
- * @param pathNames array
- * @param route object
- * @param language string
- **/
-
- function updateRoutePath$1(basePath, pathNames, route, language, convert = false) {
- if (basePath === '/' || basePath.trim().length === 0) return { result: basePath, language: null }
-
- let basePathResult = basePath;
- let routeName = route.name;
- let currentLanguage = language;
-
- if (convert) {
- currentLanguage = '';
- }
-
- routeName = removeSlash$2(routeName);
- basePathResult = removeSlash$2(basePathResult);
-
- if (!route.childRoute) {
- let localisedRoute = findLocalisedRoute(basePathResult, route, currentLanguage);
-
- if (localisedRoute.exists && convert) {
- basePathResult = routeNameLocalised$1(route, language);
- }
-
- let routeNames = routeName.split(':')[0];
- routeNames = removeSlash$2(routeNames, 'trail');
- routeNames = routeNames.split('/');
- routeNames.shift();
- routeNames.forEach(() => {
- const currentPathName = pathNames[0];
- localisedRoute = findLocalisedRoute(`${basePathResult}/${currentPathName}`, route, currentLanguage);
-
- if (currentPathName && localisedRoute.exists) {
- if (convert) {
- basePathResult = routeNameLocalised$1(route, language);
- } else {
- basePathResult = `${basePathResult}/${currentPathName}`;
- }
- pathNames.shift();
- } else {
- return { result: basePathResult, language: localisedRoute.language }
- }
- });
- return { result: basePathResult, language: localisedRoute.language }
- } else {
- return { result: basePath, language: currentLanguage }
- }
- }
-
- var utils = {
- anyEmptyNestedRoutes: anyEmptyNestedRoutes$1,
- compareRoutes,
- findLocalisedRoute,
- getNamedParams: getNamedParams$1,
- getPathNames,
- nameToPath: nameToPath$1,
- pathWithQueryParams: pathWithQueryParams$1,
- pathWithoutQueryParams: pathWithoutQueryParams$1,
- removeExtraPaths: removeExtraPaths$1,
- removeSlash: removeSlash$2,
- routeNameLocalised: routeNameLocalised$1,
- startsWithNamedParam: startsWithNamedParam$1,
- updateRoutePath: updateRoutePath$1,
- };
-
- const { UrlParser: UrlParser$2 } = urlParamsParser;
-
- const { pathWithQueryParams, removeSlash: removeSlash$1 } = utils;
-
- function RouterCurrent$1(trackPage) {
- const trackPageview = trackPage || false;
- let activeRoute = '';
-
- function setActive(newRoute, updateBrowserHistory) {
- activeRoute = newRoute.path;
- pushActiveRoute(newRoute, updateBrowserHistory);
- }
-
- function active() {
- return activeRoute
- }
-
- /**
- * Returns true if pathName is current active route
- * @param pathName String The path name to check against the current route.
- * @param includePath Boolean if true checks that pathName is included in current route. If false should match it.
- **/
- function isActive(queryPath, includePath = false) {
- if (queryPath[0] !== '/') {
- queryPath = '/' + queryPath;
- }
-
- // remove query params for comparison
- let pathName = UrlParser$2(`http://fake.com${queryPath}`).pathname;
- let activeRoutePath = UrlParser$2(`http://fake.com${activeRoute}`).pathname;
-
- pathName = removeSlash$1(pathName, 'trail');
-
- activeRoutePath = removeSlash$1(activeRoutePath, 'trail');
-
- if (includePath) {
- return activeRoutePath.includes(pathName)
- } else {
- return activeRoutePath === pathName
- }
- }
-
- function pushActiveRoute(newRoute, updateBrowserHistory) {
- if (typeof window !== 'undefined') {
- const pathAndSearch = pathWithQueryParams(newRoute);
-
- if (updateBrowserHistory) {
- window.history.pushState({ page: pathAndSearch }, '', pathAndSearch);
- }
- // Moving back in history does not update browser history but does update tracking.
- if (trackPageview) {
- gaTracking(pathAndSearch);
- }
- }
- }
-
- function gaTracking(newPage) {
- if (typeof ga !== 'undefined') {
- ga('set', 'page', newPage);
- ga('send', 'pageview');
- }
- }
-
- return Object.freeze({ active, isActive, setActive })
- }
-
- var current = { RouterCurrent: RouterCurrent$1 };
-
- function RouterGuard$1(onlyIf) {
- const guardInfo = onlyIf;
-
- function valid() {
- return guardInfo && guardInfo.guard && typeof guardInfo.guard === 'function'
- }
-
- function redirect() {
- return !guardInfo.guard()
- }
-
- function redirectPath() {
- let destinationUrl = '/';
- if (guardInfo.redirect && guardInfo.redirect.length > 0) {
- destinationUrl = guardInfo.redirect;
- }
-
- return destinationUrl
- }
-
- return Object.freeze({ valid, redirect, redirectPath })
- }
-
- var guard = { RouterGuard: RouterGuard$1 };
-
- const { RouterGuard } = guard;
-
- function RouterRedirect$1(route, currentPath) {
- const guard = RouterGuard(route.onlyIf);
-
- function path() {
- let redirectTo = currentPath;
- if (route.redirectTo && route.redirectTo.length > 0) {
- redirectTo = route.redirectTo;
- }
-
- if (guard.valid() && guard.redirect()) {
- redirectTo = guard.redirectPath();
- }
-
- return redirectTo
- }
-
- return Object.freeze({ path })
- }
-
- var redirect = { RouterRedirect: RouterRedirect$1 };
-
- const { UrlParser: UrlParser$1 } = urlParamsParser;
-
- function RouterRoute$1({ routeInfo, path, routeNamedParams, urlParser, namedPath, language }) {
- function namedParams() {
- const parsedParams = UrlParser$1(`https://fake.com${urlParser.pathname}`, namedPath).namedParams;
-
- return { ...routeNamedParams, ...parsedParams }
- }
-
- function get() {
- return {
- name: path,
- component: routeInfo.component,
- hash: urlParser.hash,
- layout: routeInfo.layout,
- queryParams: urlParser.queryParams,
- namedParams: namedParams(),
- path,
- language
- }
- }
-
- return Object.freeze({ get, namedParams })
- }
-
- var route$1 = { RouterRoute: RouterRoute$1 };
-
- const { updateRoutePath, getNamedParams, nameToPath, removeExtraPaths, routeNameLocalised } = utils;
-
- function RouterPath$1({ basePath, basePathName, pathNames, convert, currentLanguage }) {
- let updatedPathRoute;
- let route;
- let routePathLanguage = currentLanguage;
-
- function updatedPath(currentRoute) {
- route = currentRoute;
- updatedPathRoute = updateRoutePath(basePathName, pathNames, route, routePathLanguage, convert);
- routePathLanguage = convert ? currentLanguage : updatedPathRoute.language;
-
- return updatedPathRoute
- }
-
- function localisedPathName() {
- return routeNameLocalised(route, routePathLanguage)
- }
-
- function localisedRouteWithoutNamedParams() {
- return nameToPath(localisedPathName())
- }
-
- function basePathNameWithoutNamedParams() {
- return nameToPath(updatedPathRoute.result)
- }
-
- function namedPath() {
- const localisedPath = localisedPathName();
-
- return basePath ? `${basePath}/${localisedPath}` : localisedPath
- }
-
- function routePath() {
- let routePathValue = `${basePath}/${basePathNameWithoutNamedParams()}`;
- if (routePathValue === '//') {
- routePathValue = '/';
- }
-
- if (routePathLanguage) {
- pathNames = removeExtraPaths(pathNames, localisedRouteWithoutNamedParams());
- }
-
- const namedParams = getNamedParams(localisedPathName());
- if (namedParams && namedParams.length > 0) {
- namedParams.forEach(function () {
- if (pathNames.length > 0) {
- routePathValue += `/${pathNames.shift()}`;
- }
- });
- }
-
- return routePathValue
- }
-
- function routeLanguage() {
- return routePathLanguage
- }
-
- function basePathSameAsLocalised() {
- return basePathNameWithoutNamedParams() === localisedRouteWithoutNamedParams()
- }
-
- return Object.freeze({
- basePathSameAsLocalised,
- updatedPath,
- basePathNameWithoutNamedParams,
- localisedPathName,
- localisedRouteWithoutNamedParams,
- namedPath,
- pathNames,
- routeLanguage,
- routePath,
- })
- }
-
- var path$2 = { RouterPath: RouterPath$1 };
-
- const { UrlParser } = urlParamsParser;
-
- const { RouterRedirect } = redirect;
- const { RouterRoute } = route$1;
- const { RouterPath } = path$2;
- const { anyEmptyNestedRoutes, pathWithoutQueryParams, startsWithNamedParam } = utils;
-
- const NotFoundPage$1 = '/404.html';
-
- function RouterFinder$1({ routes, currentUrl, routerOptions, convert }) {
- const defaultLanguage = routerOptions.defaultLanguage;
- const sitePrefix = routerOptions.prefix ? routerOptions.prefix.toLowerCase() : '';
- const urlParser = parseCurrentUrl(currentUrl, sitePrefix);
- let redirectTo = '';
- let routeNamedParams = {};
- let staticParamMatch = false;
-
- function findActiveRoute() {
- let searchActiveRoute = searchActiveRoutes(routes, '', urlParser.pathNames, routerOptions.lang, convert);
-
- if (!searchActiveRoute || !Object.keys(searchActiveRoute).length || anyEmptyNestedRoutes(searchActiveRoute)) {
- if (typeof window !== 'undefined') {
- searchActiveRoute = routeNotFound(routerOptions.lang);
- }
- } else {
- searchActiveRoute.path = pathWithoutQueryParams(searchActiveRoute);
- if (sitePrefix) {
- searchActiveRoute.path = `/${sitePrefix}${searchActiveRoute.path}`;
- }
- }
-
- return searchActiveRoute
- }
-
- /**
- * Gets an array of routes and the browser pathname and return the active route
- * @param routes
- * @param basePath
- * @param pathNames
- **/
- function searchActiveRoutes(routes, basePath, pathNames, currentLanguage, convert) {
- let currentRoute = {};
- let basePathName = pathNames.shift().toLowerCase();
- const routerPath = RouterPath({ basePath, basePathName, pathNames, convert, currentLanguage });
- staticParamMatch = false;
-
- routes.forEach(function (route) {
- routerPath.updatedPath(route);
- if (matchRoute(routerPath, route.name)) {
- let routePath = routerPath.routePath();
- redirectTo = RouterRedirect(route, redirectTo).path();
-
- if (currentRoute.name !== routePath) {
- currentRoute = setCurrentRoute({
- route,
- routePath,
- routeLanguage: routerPath.routeLanguage(),
- urlParser,
- namedPath: routerPath.namedPath(),
- });
- }
-
- if (route.nestedRoutes && route.nestedRoutes.length > 0 && routerPath.pathNames.length > 0) {
- currentRoute.childRoute = searchActiveRoutes(
- route.nestedRoutes,
- routePath,
- routerPath.pathNames,
- routerPath.routeLanguage(),
- convert
- );
- currentRoute.path = currentRoute.childRoute.path;
- currentRoute.language = currentRoute.childRoute.language;
- } else if (nestedRoutesAndNoPath(route, routerPath.pathNames)) {
- const indexRoute = searchActiveRoutes(
- route.nestedRoutes,
- routePath,
- ['index'],
- routerPath.routeLanguage(),
- convert
- );
- if (indexRoute && Object.keys(indexRoute).length > 0) {
- currentRoute.childRoute = indexRoute;
- currentRoute.language = currentRoute.childRoute.language;
- }
- }
- }
- });
-
- if (redirectTo) {
- currentRoute.redirectTo = redirectTo;
- }
-
- return currentRoute
- }
-
- function matchRoute(routerPath, routeName) {
- const basePathSameAsLocalised = routerPath.basePathSameAsLocalised();
- if (basePathSameAsLocalised) {
- staticParamMatch = true;
- }
-
- return basePathSameAsLocalised || (!staticParamMatch && startsWithNamedParam(routeName))
- }
-
- function nestedRoutesAndNoPath(route, pathNames) {
- return route.nestedRoutes && route.nestedRoutes.length > 0 && pathNames.length === 0
- }
-
- function parseCurrentUrl(currentUrl, sitePrefix) {
- if (sitePrefix && sitePrefix.trim().length > 0) {
- const noPrefixUrl = currentUrl.replace(sitePrefix + '/', '');
- return UrlParser(noPrefixUrl)
- } else {
- return UrlParser(currentUrl)
- }
- }
-
- function setCurrentRoute({ route, routePath, routeLanguage, urlParser, namedPath }) {
- const routerRoute = RouterRoute({
- routeInfo: route,
- urlParser,
- path: routePath,
- routeNamedParams,
- namedPath,
- language: routeLanguage || defaultLanguage,
- });
- routeNamedParams = routerRoute.namedParams();
-
- return routerRoute.get()
- }
-
- function routeNotFound(customLanguage) {
- const custom404Page = routes.find((route) => route.name == '404');
- const language = customLanguage || defaultLanguage || '';
- if (custom404Page) {
- return { ...custom404Page, language, path: '404' }
- } else {
- return { name: '404', component: '', path: '404', redirectTo: NotFoundPage$1 }
- }
- }
-
- return Object.freeze({ findActiveRoute })
- }
-
- var finder = { RouterFinder: RouterFinder$1 };
-
- const { activeRoute } = store;
- const { RouterCurrent } = current;
- const { RouterFinder } = finder;
- const { removeSlash } = utils;
-
- const NotFoundPage = '/404.html';
-
- let userDefinedRoutes = [];
- let routerOptions = {};
- let routerCurrent;
-
- /**
- * Object exposes one single property: activeRoute
- * @param routes Array of routes
- * @param currentUrl current url
- * @param options configuration options
- **/
- function SpaRouter$1(routes, currentUrl, options = {}) {
- routerOptions = { ...options };
- if (typeof currentUrl === 'undefined' || currentUrl === '') {
- currentUrl = document.location.href;
- }
-
- routerCurrent = RouterCurrent(routerOptions.gaPageviews);
-
- currentUrl = removeSlash(currentUrl, 'trail');
- userDefinedRoutes = routes;
-
- function findActiveRoute() {
- let convert = false;
-
- if (routerOptions.langConvertTo) {
- routerOptions.lang = routerOptions.langConvertTo;
- convert = true;
- }
-
- return RouterFinder({ routes, currentUrl, routerOptions, convert }).findActiveRoute()
- }
-
- /**
- * Redirect current route to another
- * @param destinationUrl
- **/
- function navigateNow(destinationUrl, updateBrowserHistory) {
- if (typeof window !== 'undefined') {
- if (destinationUrl === NotFoundPage) {
- routerCurrent.setActive({ path: NotFoundPage }, updateBrowserHistory);
- } else {
- navigateTo$1(destinationUrl);
- }
- }
-
- return destinationUrl
- }
-
- function setActiveRoute(updateBrowserHistory = true) {
- const currentRoute = findActiveRoute();
- if (currentRoute.redirectTo) {
- return navigateNow(currentRoute.redirectTo, updateBrowserHistory)
- }
-
- routerCurrent.setActive(currentRoute, updateBrowserHistory);
- activeRoute.set(currentRoute);
-
- return currentRoute
- }
-
- return Object.freeze({
- setActiveRoute,
- findActiveRoute,
- })
- }
-
- /**
- * Converts a route to its localised version
- * @param pathName
- **/
- function localisedRoute$1(pathName, language) {
- pathName = removeSlash(pathName, 'lead');
- routerOptions.langConvertTo = language;
-
- return SpaRouter$1(userDefinedRoutes, 'http://fake.com/' + pathName, routerOptions).findActiveRoute()
- }
-
- /**
- * Updates the current active route and updates the browser pathname
- * @param pathName String
- * @param language String
- * @param updateBrowserHistory Boolean
- **/
- function navigateTo$1(pathName, language = null, updateBrowserHistory = true) {
- pathName = removeSlash(pathName, 'lead');
-
- if (language) {
- routerOptions.langConvertTo = language;
- }
-
- return SpaRouter$1(userDefinedRoutes, 'http://fake.com/' + pathName, routerOptions).setActiveRoute(updateBrowserHistory)
- }
-
- /**
- * Returns true if pathName is current active route
- * @param pathName String The path name to check against the current route.
- * @param includePath Boolean if true checks that pathName is included in current route. If false should match it.
- **/
- function routeIsActive$1(queryPath, includePath = false) {
- return routerCurrent.isActive(queryPath, includePath)
- }
-
- if (typeof window !== 'undefined') {
- // Avoid full page reload on local routes
- window.addEventListener('click', (event) => {
- if (event.target.localName.toLowerCase() !== 'a') return
- if (event.metaKey || event.ctrlKey || event.shiftKey) return
-
- const sitePrefix = routerOptions.prefix ? `/${routerOptions.prefix.toLowerCase()}` : '';
- const targetHostNameInternal = event.target.pathname && event.target.host === window.location.host;
- const prefixMatchPath = sitePrefix.length > 1 ? event.target.pathname.startsWith(sitePrefix) : true;
-
- if (targetHostNameInternal && prefixMatchPath) {
- event.preventDefault();
- let navigatePathname = event.target.pathname + event.target.search;
-
- const destinationUrl = navigatePathname + event.target.search + event.target.hash;
- if (event.target.target === '_blank') {
- window.open(destinationUrl, 'newTab');
- } else {
- navigateTo$1(destinationUrl);
- }
- }
- });
-
- window.onpopstate = function (_event) {
- let navigatePathname = window.location.pathname + window.location.search + window.location.hash;
-
- navigateTo$1(navigatePathname, null, false);
- };
- }
-
- var spa_router = { SpaRouter: SpaRouter$1, localisedRoute: localisedRoute$1, navigateTo: navigateTo$1, routeIsActive: routeIsActive$1 };
- var spa_router_1 = spa_router.SpaRouter;
- var spa_router_2 = spa_router.localisedRoute;
- var spa_router_3 = spa_router.navigateTo;
- var spa_router_4 = spa_router.routeIsActive;
-
- /* node_modules/svelte-router-spa/src/components/route.svelte generated by Svelte v3.59.1 */
-
- // (10:34)
- function create_if_block_2$m(ctx) {
- let route;
- let current;
-
- route = new Route$1({
- props: {
- currentRoute: /*currentRoute*/ ctx[0].childRoute,
- params: /*params*/ ctx[1]
- },
- $$inline: true
- });
-
- const block = {
- c: function create() {
- create_component(route.$$.fragment);
- },
- m: function mount(target, anchor) {
- mount_component(route, target, anchor);
- current = true;
- },
- p: function update(ctx, dirty) {
- const route_changes = {};
- if (dirty & /*currentRoute*/ 1) route_changes.currentRoute = /*currentRoute*/ ctx[0].childRoute;
- if (dirty & /*params*/ 2) route_changes.params = /*params*/ ctx[1];
- route.$set(route_changes);
- },
- i: function intro(local) {
- if (current) return;
- transition_in(route.$$.fragment, local);
- current = true;
- },
- o: function outro(local) {
- transition_out(route.$$.fragment, local);
- current = false;
- },
- d: function destroy(detaching) {
- destroy_component(route, detaching);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_if_block_2$m.name,
- type: "if",
- source: "(10:34) ",
- ctx
- });
-
- return block;
- }
-
- // (8:33)
- function create_if_block_1$u(ctx) {
- let switch_instance;
- let switch_instance_anchor;
- let current;
- var switch_value = /*currentRoute*/ ctx[0].component;
-
- function switch_props(ctx) {
- return {
- props: {
- currentRoute: {
- .../*currentRoute*/ ctx[0],
- component: ''
- },
- params: /*params*/ ctx[1]
- },
- $$inline: true
- };
- }
-
- if (switch_value) {
- switch_instance = construct_svelte_component_dev(switch_value, switch_props(ctx));
- }
-
- const block = {
- c: function create() {
- if (switch_instance) create_component(switch_instance.$$.fragment);
- switch_instance_anchor = empty();
- },
- m: function mount(target, anchor) {
- if (switch_instance) mount_component(switch_instance, target, anchor);
- insert_dev(target, switch_instance_anchor, anchor);
- current = true;
- },
- p: function update(ctx, dirty) {
- const switch_instance_changes = {};
-
- if (dirty & /*currentRoute*/ 1) switch_instance_changes.currentRoute = {
- .../*currentRoute*/ ctx[0],
- component: ''
- };
-
- if (dirty & /*params*/ 2) switch_instance_changes.params = /*params*/ ctx[1];
-
- if (dirty & /*currentRoute*/ 1 && switch_value !== (switch_value = /*currentRoute*/ ctx[0].component)) {
- if (switch_instance) {
- group_outros();
- const old_component = switch_instance;
-
- transition_out(old_component.$$.fragment, 1, 0, () => {
- destroy_component(old_component, 1);
- });
-
- check_outros();
- }
-
- if (switch_value) {
- switch_instance = construct_svelte_component_dev(switch_value, switch_props(ctx));
- create_component(switch_instance.$$.fragment);
- transition_in(switch_instance.$$.fragment, 1);
- mount_component(switch_instance, switch_instance_anchor.parentNode, switch_instance_anchor);
- } else {
- switch_instance = null;
- }
- } else if (switch_value) {
- switch_instance.$set(switch_instance_changes);
- }
- },
- i: function intro(local) {
- if (current) return;
- if (switch_instance) transition_in(switch_instance.$$.fragment, local);
- current = true;
- },
- o: function outro(local) {
- if (switch_instance) transition_out(switch_instance.$$.fragment, local);
- current = false;
- },
- d: function destroy(detaching) {
- if (detaching) detach_dev(switch_instance_anchor);
- if (switch_instance) destroy_component(switch_instance, detaching);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_if_block_1$u.name,
- type: "if",
- source: "(8:33) ",
- ctx
- });
-
- return block;
- }
-
- // (6:0) {#if currentRoute.layout}
- function create_if_block$H(ctx) {
- let switch_instance;
- let switch_instance_anchor;
- let current;
- var switch_value = /*currentRoute*/ ctx[0].layout;
-
- function switch_props(ctx) {
- return {
- props: {
- currentRoute: { .../*currentRoute*/ ctx[0], layout: '' },
- params: /*params*/ ctx[1]
- },
- $$inline: true
- };
- }
-
- if (switch_value) {
- switch_instance = construct_svelte_component_dev(switch_value, switch_props(ctx));
- }
-
- const block = {
- c: function create() {
- if (switch_instance) create_component(switch_instance.$$.fragment);
- switch_instance_anchor = empty();
- },
- m: function mount(target, anchor) {
- if (switch_instance) mount_component(switch_instance, target, anchor);
- insert_dev(target, switch_instance_anchor, anchor);
- current = true;
- },
- p: function update(ctx, dirty) {
- const switch_instance_changes = {};
- if (dirty & /*currentRoute*/ 1) switch_instance_changes.currentRoute = { .../*currentRoute*/ ctx[0], layout: '' };
- if (dirty & /*params*/ 2) switch_instance_changes.params = /*params*/ ctx[1];
-
- if (dirty & /*currentRoute*/ 1 && switch_value !== (switch_value = /*currentRoute*/ ctx[0].layout)) {
- if (switch_instance) {
- group_outros();
- const old_component = switch_instance;
-
- transition_out(old_component.$$.fragment, 1, 0, () => {
- destroy_component(old_component, 1);
- });
-
- check_outros();
- }
-
- if (switch_value) {
- switch_instance = construct_svelte_component_dev(switch_value, switch_props(ctx));
- create_component(switch_instance.$$.fragment);
- transition_in(switch_instance.$$.fragment, 1);
- mount_component(switch_instance, switch_instance_anchor.parentNode, switch_instance_anchor);
- } else {
- switch_instance = null;
- }
- } else if (switch_value) {
- switch_instance.$set(switch_instance_changes);
- }
- },
- i: function intro(local) {
- if (current) return;
- if (switch_instance) transition_in(switch_instance.$$.fragment, local);
- current = true;
- },
- o: function outro(local) {
- if (switch_instance) transition_out(switch_instance.$$.fragment, local);
- current = false;
- },
- d: function destroy(detaching) {
- if (detaching) detach_dev(switch_instance_anchor);
- if (switch_instance) destroy_component(switch_instance, detaching);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_if_block$H.name,
- type: "if",
- source: "(6:0) {#if currentRoute.layout}",
- ctx
- });
-
- return block;
- }
-
- function create_fragment$W(ctx) {
- let current_block_type_index;
- let if_block;
- let if_block_anchor;
- let current;
- const if_block_creators = [create_if_block$H, create_if_block_1$u, create_if_block_2$m];
- const if_blocks = [];
-
- function select_block_type(ctx, dirty) {
- if (/*currentRoute*/ ctx[0].layout) return 0;
- if (/*currentRoute*/ ctx[0].component) return 1;
- if (/*currentRoute*/ ctx[0].childRoute) return 2;
- return -1;
- }
-
- if (~(current_block_type_index = select_block_type(ctx))) {
- if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
- }
-
- const block = {
- c: function create() {
- if (if_block) if_block.c();
- if_block_anchor = empty();
- },
- l: function claim(nodes) {
- throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
- },
- m: function mount(target, anchor) {
- if (~current_block_type_index) {
- if_blocks[current_block_type_index].m(target, anchor);
- }
-
- insert_dev(target, if_block_anchor, anchor);
- current = true;
- },
- p: function update(ctx, [dirty]) {
- let previous_block_index = current_block_type_index;
- current_block_type_index = select_block_type(ctx);
-
- if (current_block_type_index === previous_block_index) {
- if (~current_block_type_index) {
- if_blocks[current_block_type_index].p(ctx, dirty);
- }
- } else {
- if (if_block) {
- group_outros();
-
- transition_out(if_blocks[previous_block_index], 1, 1, () => {
- if_blocks[previous_block_index] = null;
- });
-
- check_outros();
- }
-
- if (~current_block_type_index) {
- if_block = if_blocks[current_block_type_index];
-
- if (!if_block) {
- if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx);
- if_block.c();
- } else {
- if_block.p(ctx, dirty);
- }
-
- transition_in(if_block, 1);
- if_block.m(if_block_anchor.parentNode, if_block_anchor);
- } else {
- if_block = null;
- }
- }
- },
- i: function intro(local) {
- if (current) return;
- transition_in(if_block);
- current = true;
- },
- o: function outro(local) {
- transition_out(if_block);
- current = false;
- },
- d: function destroy(detaching) {
- if (~current_block_type_index) {
- if_blocks[current_block_type_index].d(detaching);
- }
-
- if (detaching) detach_dev(if_block_anchor);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_fragment$W.name,
- type: "component",
- source: "",
- ctx
- });
-
- return block;
- }
-
- function instance$W($$self, $$props, $$invalidate) {
- let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots('Route', slots, []);
- let { currentRoute = {} } = $$props;
- let { params = {} } = $$props;
- const writable_props = ['currentRoute', 'params'];
-
- Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
- });
-
- $$self.$$set = $$props => {
- if ('currentRoute' in $$props) $$invalidate(0, currentRoute = $$props.currentRoute);
- if ('params' in $$props) $$invalidate(1, params = $$props.params);
- };
-
- $$self.$capture_state = () => ({ currentRoute, params });
-
- $$self.$inject_state = $$props => {
- if ('currentRoute' in $$props) $$invalidate(0, currentRoute = $$props.currentRoute);
- if ('params' in $$props) $$invalidate(1, params = $$props.params);
- };
-
- if ($$props && "$$inject" in $$props) {
- $$self.$inject_state($$props.$$inject);
- }
-
- return [currentRoute, params];
- }
-
- class Route$1 extends SvelteComponentDev {
- constructor(options) {
- super(options);
- init(this, options, instance$W, create_fragment$W, safe_not_equal, { currentRoute: 0, params: 1 });
-
- dispatch_dev("SvelteRegisterComponent", {
- component: this,
- tagName: "Route",
- options,
- id: create_fragment$W.name
- });
- }
-
- get currentRoute() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set currentRoute(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
-
- get params() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set params(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
- }
-
- var route = /*#__PURE__*/Object.freeze({
- __proto__: null,
- 'default': Route$1
- });
-
- /* node_modules/svelte-router-spa/src/components/router.svelte generated by Svelte v3.59.1 */
-
- function create_fragment$V(ctx) {
- let route;
- let current;
-
- route = new Route$1({
- props: { currentRoute: /*$activeRoute*/ ctx[0] },
- $$inline: true
- });
-
- const block = {
- c: function create() {
- create_component(route.$$.fragment);
- },
- l: function claim(nodes) {
- throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
- },
- m: function mount(target, anchor) {
- mount_component(route, target, anchor);
- current = true;
- },
- p: function update(ctx, [dirty]) {
- const route_changes = {};
- if (dirty & /*$activeRoute*/ 1) route_changes.currentRoute = /*$activeRoute*/ ctx[0];
- route.$set(route_changes);
- },
- i: function intro(local) {
- if (current) return;
- transition_in(route.$$.fragment, local);
- current = true;
- },
- o: function outro(local) {
- transition_out(route.$$.fragment, local);
- current = false;
- },
- d: function destroy(detaching) {
- destroy_component(route, detaching);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_fragment$V.name,
- type: "component",
- source: "",
- ctx
- });
-
- return block;
- }
-
- function instance$V($$self, $$props, $$invalidate) {
- let $activeRoute;
- validate_store(store_1, 'activeRoute');
- component_subscribe($$self, store_1, $$value => $$invalidate(0, $activeRoute = $$value));
- let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots('Router', slots, []);
- let { routes = [] } = $$props;
- let { options = {} } = $$props;
-
- onMount(function () {
- spa_router_1(routes, document.location.href, options).setActiveRoute();
- });
-
- const writable_props = ['routes', 'options'];
-
- Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
- });
-
- $$self.$$set = $$props => {
- if ('routes' in $$props) $$invalidate(1, routes = $$props.routes);
- if ('options' in $$props) $$invalidate(2, options = $$props.options);
- };
-
- $$self.$capture_state = () => ({
- onMount,
- SpaRouter: spa_router_1,
- Route: Route$1,
- activeRoute: store_1,
- routes,
- options,
- $activeRoute
- });
-
- $$self.$inject_state = $$props => {
- if ('routes' in $$props) $$invalidate(1, routes = $$props.routes);
- if ('options' in $$props) $$invalidate(2, options = $$props.options);
- };
-
- if ($$props && "$$inject" in $$props) {
- $$self.$inject_state($$props.$$inject);
- }
-
- return [$activeRoute, routes, options];
- }
-
- class Router$1 extends SvelteComponentDev {
- constructor(options) {
- super(options);
- init(this, options, instance$V, create_fragment$V, safe_not_equal, { routes: 1, options: 2 });
-
- dispatch_dev("SvelteRegisterComponent", {
- component: this,
- tagName: "Router",
- options,
- id: create_fragment$V.name
- });
- }
-
- get routes() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set routes(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
-
- get options() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set options(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
- }
-
- var router = /*#__PURE__*/Object.freeze({
- __proto__: null,
- 'default': Router$1
- });
-
- /* node_modules/svelte-router-spa/src/components/navigate.svelte generated by Svelte v3.59.1 */
- const file$U = "node_modules/svelte-router-spa/src/components/navigate.svelte";
-
- function create_fragment$U(ctx) {
- let a;
- let current;
- let mounted;
- let dispose;
- const default_slot_template = /*#slots*/ ctx[6].default;
- const default_slot = create_slot(default_slot_template, ctx, /*$$scope*/ ctx[5], null);
-
- const block = {
- c: function create() {
- a = element("a");
- if (default_slot) default_slot.c();
- attr_dev(a, "href", /*to*/ ctx[0]);
- attr_dev(a, "title", /*title*/ ctx[1]);
- attr_dev(a, "class", /*styles*/ ctx[2]);
- toggle_class(a, "active", spa_router_4(/*to*/ ctx[0]));
- add_location(a, file$U, 25, 0, 548);
- },
- l: function claim(nodes) {
- throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
- },
- m: function mount(target, anchor) {
- insert_dev(target, a, anchor);
-
- if (default_slot) {
- default_slot.m(a, null);
- }
-
- current = true;
-
- if (!mounted) {
- dispose = listen_dev(a, "click", /*navigate*/ ctx[3], false, false, false, false);
- mounted = true;
- }
- },
- p: function update(ctx, [dirty]) {
- if (default_slot) {
- if (default_slot.p && (!current || dirty & /*$$scope*/ 32)) {
- update_slot_base(
- default_slot,
- default_slot_template,
- ctx,
- /*$$scope*/ ctx[5],
- !current
- ? get_all_dirty_from_scope(/*$$scope*/ ctx[5])
- : get_slot_changes(default_slot_template, /*$$scope*/ ctx[5], dirty, null),
- null
- );
- }
- }
-
- if (!current || dirty & /*to*/ 1) {
- attr_dev(a, "href", /*to*/ ctx[0]);
- }
-
- if (!current || dirty & /*title*/ 2) {
- attr_dev(a, "title", /*title*/ ctx[1]);
- }
-
- if (!current || dirty & /*styles*/ 4) {
- attr_dev(a, "class", /*styles*/ ctx[2]);
- }
-
- if (!current || dirty & /*styles, routeIsActive, to*/ 5) {
- toggle_class(a, "active", spa_router_4(/*to*/ ctx[0]));
- }
- },
- i: function intro(local) {
- if (current) return;
- transition_in(default_slot, local);
- current = true;
- },
- o: function outro(local) {
- transition_out(default_slot, local);
- current = false;
- },
- d: function destroy(detaching) {
- if (detaching) detach_dev(a);
- if (default_slot) default_slot.d(detaching);
- mounted = false;
- dispose();
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_fragment$U.name,
- type: "component",
- source: "",
- ctx
- });
-
- return block;
- }
-
- function instance$U($$self, $$props, $$invalidate) {
- let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots('Navigate', slots, ['default']);
- let { to = '/' } = $$props;
- let { title = '' } = $$props;
- let { styles = '' } = $$props;
- let { lang = null } = $$props;
-
- onMount(function () {
- if (lang) {
- const route = spa_router_2(to, lang);
-
- if (route) {
- $$invalidate(0, to = route.path);
- }
- }
- });
-
- function navigate(event) {
- if (event.metaKey || event.ctrlKey || event.shiftKey) return;
- event.preventDefault();
- event.stopPropagation();
- spa_router_3(to);
- }
-
- const writable_props = ['to', 'title', 'styles', 'lang'];
-
- Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
- });
-
- $$self.$$set = $$props => {
- if ('to' in $$props) $$invalidate(0, to = $$props.to);
- if ('title' in $$props) $$invalidate(1, title = $$props.title);
- if ('styles' in $$props) $$invalidate(2, styles = $$props.styles);
- if ('lang' in $$props) $$invalidate(4, lang = $$props.lang);
- if ('$$scope' in $$props) $$invalidate(5, $$scope = $$props.$$scope);
- };
-
- $$self.$capture_state = () => ({
- onMount,
- localisedRoute: spa_router_2,
- navigateTo: spa_router_3,
- routeIsActive: spa_router_4,
- to,
- title,
- styles,
- lang,
- navigate
- });
-
- $$self.$inject_state = $$props => {
- if ('to' in $$props) $$invalidate(0, to = $$props.to);
- if ('title' in $$props) $$invalidate(1, title = $$props.title);
- if ('styles' in $$props) $$invalidate(2, styles = $$props.styles);
- if ('lang' in $$props) $$invalidate(4, lang = $$props.lang);
- };
-
- if ($$props && "$$inject" in $$props) {
- $$self.$inject_state($$props.$$inject);
- }
-
- return [to, title, styles, navigate, lang, $$scope, slots];
- }
-
- class Navigate$1 extends SvelteComponentDev {
- constructor(options) {
- super(options);
- init(this, options, instance$U, create_fragment$U, safe_not_equal, { to: 0, title: 1, styles: 2, lang: 4 });
-
- dispatch_dev("SvelteRegisterComponent", {
- component: this,
- tagName: "Navigate",
- options,
- id: create_fragment$U.name
- });
- }
-
- get to() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set to(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
-
- get title() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set title(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
-
- get styles() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set styles(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
-
- get lang() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set lang(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
- }
-
- var navigate = /*#__PURE__*/Object.freeze({
- __proto__: null,
- 'default': Navigate$1
- });
-
- var Route = getCjsExportFromNamespace(route);
-
- var Router = getCjsExportFromNamespace(router);
-
- var Navigate = getCjsExportFromNamespace(navigate);
-
- const { SpaRouter, navigateTo, localisedRoute, routeIsActive } = spa_router;
-
-
-
-
- var src = {
- SpaRouter,
- localisedRoute,
- navigateTo,
- routeIsActive,
- Route,
- Router,
- Navigate
- };
- var src_3 = src.navigateTo;
- var src_5 = src.Route;
- var src_6 = src.Router;
- var src_7 = src.Navigate;
-
- /******************************************************************************
- Copyright (c) Microsoft Corporation.
-
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
- ***************************************************************************** */
-
- function __rest(s, e) {
- var t = {};
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
- t[p] = s[p];
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
- t[p[i]] = s[p[i]];
- }
- return t;
- }
-
- /**
- * Enumeration of supported providers.
- *
- * @public
- */
- const ProviderId = {
- /** Facebook provider ID */
- FACEBOOK: 'facebook.com',
- /** GitHub provider ID */
- GITHUB: 'github.com',
- /** Google provider ID */
- GOOGLE: 'google.com',
- /** Password provider */
- PASSWORD: 'password',
- /** Phone provider */
- PHONE: 'phone',
- /** Twitter provider ID */
- TWITTER: 'twitter.com'
- };
- /**
- * An enumeration of the possible email action types.
- *
- * @public
- */
- const ActionCodeOperation = {
- /** The email link sign-in action. */
- EMAIL_SIGNIN: 'EMAIL_SIGNIN',
- /** The password reset action. */
- PASSWORD_RESET: 'PASSWORD_RESET',
- /** The email revocation action. */
- RECOVER_EMAIL: 'RECOVER_EMAIL',
- /** The revert second factor addition email action. */
- REVERT_SECOND_FACTOR_ADDITION: 'REVERT_SECOND_FACTOR_ADDITION',
- /** The revert second factor addition email action. */
- VERIFY_AND_CHANGE_EMAIL: 'VERIFY_AND_CHANGE_EMAIL',
- /** The email verification action. */
- VERIFY_EMAIL: 'VERIFY_EMAIL'
- };
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _debugErrorMap() {
- return {
- ["admin-restricted-operation" /* AuthErrorCode.ADMIN_ONLY_OPERATION */]: 'This operation is restricted to administrators only.',
- ["argument-error" /* AuthErrorCode.ARGUMENT_ERROR */]: '',
- ["app-not-authorized" /* AuthErrorCode.APP_NOT_AUTHORIZED */]: "This app, identified by the domain where it's hosted, is not " +
- 'authorized to use Firebase Authentication with the provided API key. ' +
- 'Review your key configuration in the Google API console.',
- ["app-not-installed" /* AuthErrorCode.APP_NOT_INSTALLED */]: 'The requested mobile application corresponding to the identifier (' +
- 'Android package name or iOS bundle ID) provided is not installed on ' +
- 'this device.',
- ["captcha-check-failed" /* AuthErrorCode.CAPTCHA_CHECK_FAILED */]: 'The reCAPTCHA response token provided is either invalid, expired, ' +
- 'already used or the domain associated with it does not match the list ' +
- 'of whitelisted domains.',
- ["code-expired" /* AuthErrorCode.CODE_EXPIRED */]: 'The SMS code has expired. Please re-send the verification code to try ' +
- 'again.',
- ["cordova-not-ready" /* AuthErrorCode.CORDOVA_NOT_READY */]: 'Cordova framework is not ready.',
- ["cors-unsupported" /* AuthErrorCode.CORS_UNSUPPORTED */]: 'This browser is not supported.',
- ["credential-already-in-use" /* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */]: 'This credential is already associated with a different user account.',
- ["custom-token-mismatch" /* AuthErrorCode.CREDENTIAL_MISMATCH */]: 'The custom token corresponds to a different audience.',
- ["requires-recent-login" /* AuthErrorCode.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */]: 'This operation is sensitive and requires recent authentication. Log in ' +
- 'again before retrying this request.',
- ["dependent-sdk-initialized-before-auth" /* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */]: 'Another Firebase SDK was initialized and is trying to use Auth before Auth is ' +
- 'initialized. Please be sure to call `initializeAuth` or `getAuth` before ' +
- 'starting any other Firebase SDK.',
- ["dynamic-link-not-activated" /* AuthErrorCode.DYNAMIC_LINK_NOT_ACTIVATED */]: 'Please activate Dynamic Links in the Firebase Console and agree to the terms and ' +
- 'conditions.',
- ["email-change-needs-verification" /* AuthErrorCode.EMAIL_CHANGE_NEEDS_VERIFICATION */]: 'Multi-factor users must always have a verified email.',
- ["email-already-in-use" /* AuthErrorCode.EMAIL_EXISTS */]: 'The email address is already in use by another account.',
- ["emulator-config-failed" /* AuthErrorCode.EMULATOR_CONFIG_FAILED */]: 'Auth instance has already been used to make a network call. Auth can ' +
- 'no longer be configured to use the emulator. Try calling ' +
- '"connectAuthEmulator()" sooner.',
- ["expired-action-code" /* AuthErrorCode.EXPIRED_OOB_CODE */]: 'The action code has expired.',
- ["cancelled-popup-request" /* AuthErrorCode.EXPIRED_POPUP_REQUEST */]: 'This operation has been cancelled due to another conflicting popup being opened.',
- ["internal-error" /* AuthErrorCode.INTERNAL_ERROR */]: 'An internal AuthError has occurred.',
- ["invalid-app-credential" /* AuthErrorCode.INVALID_APP_CREDENTIAL */]: 'The phone verification request contains an invalid application verifier.' +
- ' The reCAPTCHA token response is either invalid or expired.',
- ["invalid-app-id" /* AuthErrorCode.INVALID_APP_ID */]: 'The mobile app identifier is not registed for the current project.',
- ["invalid-user-token" /* AuthErrorCode.INVALID_AUTH */]: "This user's credential isn't valid for this project. This can happen " +
- "if the user's token has been tampered with, or if the user isn't for " +
- 'the project associated with this API key.',
- ["invalid-auth-event" /* AuthErrorCode.INVALID_AUTH_EVENT */]: 'An internal AuthError has occurred.',
- ["invalid-verification-code" /* AuthErrorCode.INVALID_CODE */]: 'The SMS verification code used to create the phone auth credential is ' +
- 'invalid. Please resend the verification code sms and be sure to use the ' +
- 'verification code provided by the user.',
- ["invalid-continue-uri" /* AuthErrorCode.INVALID_CONTINUE_URI */]: 'The continue URL provided in the request is invalid.',
- ["invalid-cordova-configuration" /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */]: 'The following Cordova plugins must be installed to enable OAuth sign-in: ' +
- 'cordova-plugin-buildinfo, cordova-universal-links-plugin, ' +
- 'cordova-plugin-browsertab, cordova-plugin-inappbrowser and ' +
- 'cordova-plugin-customurlscheme.',
- ["invalid-custom-token" /* AuthErrorCode.INVALID_CUSTOM_TOKEN */]: 'The custom token format is incorrect. Please check the documentation.',
- ["invalid-dynamic-link-domain" /* AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN */]: 'The provided dynamic link domain is not configured or authorized for the current project.',
- ["invalid-email" /* AuthErrorCode.INVALID_EMAIL */]: 'The email address is badly formatted.',
- ["invalid-emulator-scheme" /* AuthErrorCode.INVALID_EMULATOR_SCHEME */]: 'Emulator URL must start with a valid scheme (http:// or https://).',
- ["invalid-api-key" /* AuthErrorCode.INVALID_API_KEY */]: 'Your API key is invalid, please check you have copied it correctly.',
- ["invalid-cert-hash" /* AuthErrorCode.INVALID_CERT_HASH */]: 'The SHA-1 certificate hash provided is invalid.',
- ["invalid-credential" /* AuthErrorCode.INVALID_IDP_RESPONSE */]: 'The supplied auth credential is malformed or has expired.',
- ["invalid-message-payload" /* AuthErrorCode.INVALID_MESSAGE_PAYLOAD */]: 'The email template corresponding to this action contains invalid characters in its message. ' +
- 'Please fix by going to the Auth email templates section in the Firebase Console.',
- ["invalid-multi-factor-session" /* AuthErrorCode.INVALID_MFA_SESSION */]: 'The request does not contain a valid proof of first factor successful sign-in.',
- ["invalid-oauth-provider" /* AuthErrorCode.INVALID_OAUTH_PROVIDER */]: 'EmailAuthProvider is not supported for this operation. This operation ' +
- 'only supports OAuth providers.',
- ["invalid-oauth-client-id" /* AuthErrorCode.INVALID_OAUTH_CLIENT_ID */]: 'The OAuth client ID provided is either invalid or does not match the ' +
- 'specified API key.',
- ["unauthorized-domain" /* AuthErrorCode.INVALID_ORIGIN */]: 'This domain is not authorized for OAuth operations for your Firebase ' +
- 'project. Edit the list of authorized domains from the Firebase console.',
- ["invalid-action-code" /* AuthErrorCode.INVALID_OOB_CODE */]: 'The action code is invalid. This can happen if the code is malformed, ' +
- 'expired, or has already been used.',
- ["wrong-password" /* AuthErrorCode.INVALID_PASSWORD */]: 'The password is invalid or the user does not have a password.',
- ["invalid-persistence-type" /* AuthErrorCode.INVALID_PERSISTENCE */]: 'The specified persistence type is invalid. It can only be local, session or none.',
- ["invalid-phone-number" /* AuthErrorCode.INVALID_PHONE_NUMBER */]: 'The format of the phone number provided is incorrect. Please enter the ' +
- 'phone number in a format that can be parsed into E.164 format. E.164 ' +
- 'phone numbers are written in the format [+][country code][subscriber ' +
- 'number including area code].',
- ["invalid-provider-id" /* AuthErrorCode.INVALID_PROVIDER_ID */]: 'The specified provider ID is invalid.',
- ["invalid-recipient-email" /* AuthErrorCode.INVALID_RECIPIENT_EMAIL */]: 'The email corresponding to this action failed to send as the provided ' +
- 'recipient email address is invalid.',
- ["invalid-sender" /* AuthErrorCode.INVALID_SENDER */]: 'The email template corresponding to this action contains an invalid sender email or name. ' +
- 'Please fix by going to the Auth email templates section in the Firebase Console.',
- ["invalid-verification-id" /* AuthErrorCode.INVALID_SESSION_INFO */]: 'The verification ID used to create the phone auth credential is invalid.',
- ["invalid-tenant-id" /* AuthErrorCode.INVALID_TENANT_ID */]: "The Auth instance's tenant ID is invalid.",
- ["login-blocked" /* AuthErrorCode.LOGIN_BLOCKED */]: 'Login blocked by user-provided method: {$originalMessage}',
- ["missing-android-pkg-name" /* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */]: 'An Android Package Name must be provided if the Android App is required to be installed.',
- ["auth-domain-config-required" /* AuthErrorCode.MISSING_AUTH_DOMAIN */]: 'Be sure to include authDomain when calling firebase.initializeApp(), ' +
- 'by following the instructions in the Firebase console.',
- ["missing-app-credential" /* AuthErrorCode.MISSING_APP_CREDENTIAL */]: 'The phone verification request is missing an application verifier ' +
- 'assertion. A reCAPTCHA response token needs to be provided.',
- ["missing-verification-code" /* AuthErrorCode.MISSING_CODE */]: 'The phone auth credential was created with an empty SMS verification code.',
- ["missing-continue-uri" /* AuthErrorCode.MISSING_CONTINUE_URI */]: 'A continue URL must be provided in the request.',
- ["missing-iframe-start" /* AuthErrorCode.MISSING_IFRAME_START */]: 'An internal AuthError has occurred.',
- ["missing-ios-bundle-id" /* AuthErrorCode.MISSING_IOS_BUNDLE_ID */]: 'An iOS Bundle ID must be provided if an App Store ID is provided.',
- ["missing-or-invalid-nonce" /* AuthErrorCode.MISSING_OR_INVALID_NONCE */]: 'The request does not contain a valid nonce. This can occur if the ' +
- 'SHA-256 hash of the provided raw nonce does not match the hashed nonce ' +
- 'in the ID token payload.',
- ["missing-password" /* AuthErrorCode.MISSING_PASSWORD */]: 'A non-empty password must be provided',
- ["missing-multi-factor-info" /* AuthErrorCode.MISSING_MFA_INFO */]: 'No second factor identifier is provided.',
- ["missing-multi-factor-session" /* AuthErrorCode.MISSING_MFA_SESSION */]: 'The request is missing proof of first factor successful sign-in.',
- ["missing-phone-number" /* AuthErrorCode.MISSING_PHONE_NUMBER */]: 'To send verification codes, provide a phone number for the recipient.',
- ["missing-verification-id" /* AuthErrorCode.MISSING_SESSION_INFO */]: 'The phone auth credential was created with an empty verification ID.',
- ["app-deleted" /* AuthErrorCode.MODULE_DESTROYED */]: 'This instance of FirebaseApp has been deleted.',
- ["multi-factor-info-not-found" /* AuthErrorCode.MFA_INFO_NOT_FOUND */]: 'The user does not have a second factor matching the identifier provided.',
- ["multi-factor-auth-required" /* AuthErrorCode.MFA_REQUIRED */]: 'Proof of ownership of a second factor is required to complete sign-in.',
- ["account-exists-with-different-credential" /* AuthErrorCode.NEED_CONFIRMATION */]: 'An account already exists with the same email address but different ' +
- 'sign-in credentials. Sign in using a provider associated with this ' +
- 'email address.',
- ["network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */]: 'A network AuthError (such as timeout, interrupted connection or unreachable host) has occurred.',
- ["no-auth-event" /* AuthErrorCode.NO_AUTH_EVENT */]: 'An internal AuthError has occurred.',
- ["no-such-provider" /* AuthErrorCode.NO_SUCH_PROVIDER */]: 'User was not linked to an account with the given provider.',
- ["null-user" /* AuthErrorCode.NULL_USER */]: 'A null user object was provided as the argument for an operation which ' +
- 'requires a non-null user object.',
- ["operation-not-allowed" /* AuthErrorCode.OPERATION_NOT_ALLOWED */]: 'The given sign-in provider is disabled for this Firebase project. ' +
- 'Enable it in the Firebase console, under the sign-in method tab of the ' +
- 'Auth section.',
- ["operation-not-supported-in-this-environment" /* AuthErrorCode.OPERATION_NOT_SUPPORTED */]: 'This operation is not supported in the environment this application is ' +
- 'running on. "location.protocol" must be http, https or chrome-extension' +
- ' and web storage must be enabled.',
- ["popup-blocked" /* AuthErrorCode.POPUP_BLOCKED */]: 'Unable to establish a connection with the popup. It may have been blocked by the browser.',
- ["popup-closed-by-user" /* AuthErrorCode.POPUP_CLOSED_BY_USER */]: 'The popup has been closed by the user before finalizing the operation.',
- ["provider-already-linked" /* AuthErrorCode.PROVIDER_ALREADY_LINKED */]: 'User can only be linked to one identity for the given provider.',
- ["quota-exceeded" /* AuthErrorCode.QUOTA_EXCEEDED */]: "The project's quota for this operation has been exceeded.",
- ["redirect-cancelled-by-user" /* AuthErrorCode.REDIRECT_CANCELLED_BY_USER */]: 'The redirect operation has been cancelled by the user before finalizing.',
- ["redirect-operation-pending" /* AuthErrorCode.REDIRECT_OPERATION_PENDING */]: 'A redirect sign-in operation is already pending.',
- ["rejected-credential" /* AuthErrorCode.REJECTED_CREDENTIAL */]: 'The request contains malformed or mismatching credentials.',
- ["second-factor-already-in-use" /* AuthErrorCode.SECOND_FACTOR_ALREADY_ENROLLED */]: 'The second factor is already enrolled on this account.',
- ["maximum-second-factor-count-exceeded" /* AuthErrorCode.SECOND_FACTOR_LIMIT_EXCEEDED */]: 'The maximum allowed number of second factors on a user has been exceeded.',
- ["tenant-id-mismatch" /* AuthErrorCode.TENANT_ID_MISMATCH */]: "The provided tenant ID does not match the Auth instance's tenant ID",
- ["timeout" /* AuthErrorCode.TIMEOUT */]: 'The operation has timed out.',
- ["user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */]: "The user's credential is no longer valid. The user must sign in again.",
- ["too-many-requests" /* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */]: 'We have blocked all requests from this device due to unusual activity. ' +
- 'Try again later.',
- ["unauthorized-continue-uri" /* AuthErrorCode.UNAUTHORIZED_DOMAIN */]: 'The domain of the continue URL is not whitelisted. Please whitelist ' +
- 'the domain in the Firebase console.',
- ["unsupported-first-factor" /* AuthErrorCode.UNSUPPORTED_FIRST_FACTOR */]: 'Enrolling a second factor or signing in with a multi-factor account requires sign-in with a supported first factor.',
- ["unsupported-persistence-type" /* AuthErrorCode.UNSUPPORTED_PERSISTENCE */]: 'The current environment does not support the specified persistence type.',
- ["unsupported-tenant-operation" /* AuthErrorCode.UNSUPPORTED_TENANT_OPERATION */]: 'This operation is not supported in a multi-tenant context.',
- ["unverified-email" /* AuthErrorCode.UNVERIFIED_EMAIL */]: 'The operation requires a verified email.',
- ["user-cancelled" /* AuthErrorCode.USER_CANCELLED */]: 'The user did not grant your application the permissions it requested.',
- ["user-not-found" /* AuthErrorCode.USER_DELETED */]: 'There is no user record corresponding to this identifier. The user may ' +
- 'have been deleted.',
- ["user-disabled" /* AuthErrorCode.USER_DISABLED */]: 'The user account has been disabled by an administrator.',
- ["user-mismatch" /* AuthErrorCode.USER_MISMATCH */]: 'The supplied credentials do not correspond to the previously signed in user.',
- ["user-signed-out" /* AuthErrorCode.USER_SIGNED_OUT */]: '',
- ["weak-password" /* AuthErrorCode.WEAK_PASSWORD */]: 'The password must be 6 characters long or more.',
- ["web-storage-unsupported" /* AuthErrorCode.WEB_STORAGE_UNSUPPORTED */]: 'This browser is not supported or 3rd party cookies and data may be disabled.',
- ["already-initialized" /* AuthErrorCode.ALREADY_INITIALIZED */]: 'initializeAuth() has already been called with ' +
- 'different options. To avoid this error, call initializeAuth() with the ' +
- 'same options as when it was originally called, or call getAuth() to return the' +
- ' already initialized instance.',
- ["missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */]: 'The reCAPTCHA token is missing when sending request to the backend.',
- ["invalid-recaptcha-token" /* AuthErrorCode.INVALID_RECAPTCHA_TOKEN */]: 'The reCAPTCHA token is invalid when sending request to the backend.',
- ["invalid-recaptcha-action" /* AuthErrorCode.INVALID_RECAPTCHA_ACTION */]: 'The reCAPTCHA action is invalid when sending request to the backend.',
- ["recaptcha-not-enabled" /* AuthErrorCode.RECAPTCHA_NOT_ENABLED */]: 'reCAPTCHA Enterprise integration is not enabled for this project.',
- ["missing-client-type" /* AuthErrorCode.MISSING_CLIENT_TYPE */]: 'The reCAPTCHA client type is missing when sending request to the backend.',
- ["missing-recaptcha-version" /* AuthErrorCode.MISSING_RECAPTCHA_VERSION */]: 'The reCAPTCHA version is missing when sending request to the backend.',
- ["invalid-req-type" /* AuthErrorCode.INVALID_REQ_TYPE */]: 'Invalid request parameters.',
- ["invalid-recaptcha-version" /* AuthErrorCode.INVALID_RECAPTCHA_VERSION */]: 'The reCAPTCHA version is invalid when sending request to the backend.'
- };
- }
- function _prodErrorMap() {
- // We will include this one message in the prod error map since by the very
- // nature of this error, developers will never be able to see the message
- // using the debugErrorMap (which is installed during auth initialization).
- return {
- ["dependent-sdk-initialized-before-auth" /* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */]: 'Another Firebase SDK was initialized and is trying to use Auth before Auth is ' +
- 'initialized. Please be sure to call `initializeAuth` or `getAuth` before ' +
- 'starting any other Firebase SDK.'
- };
- }
- /**
- * A verbose error map with detailed descriptions for most error codes.
- *
- * See discussion at {@link AuthErrorMap}
- *
- * @public
- */
- const debugErrorMap = _debugErrorMap;
- /**
- * A minimal error map with all verbose error messages stripped.
- *
- * See discussion at {@link AuthErrorMap}
- *
- * @public
- */
- const prodErrorMap = _prodErrorMap;
- const _DEFAULT_AUTH_ERROR_FACTORY = new ErrorFactory('auth', 'Firebase', _prodErrorMap());
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const logClient = new Logger('@firebase/auth');
- function _logWarn(msg, ...args) {
- if (logClient.logLevel <= LogLevel.WARN) {
- logClient.warn(`Auth (${SDK_VERSION$1}): ${msg}`, ...args);
- }
- }
- function _logError(msg, ...args) {
- if (logClient.logLevel <= LogLevel.ERROR) {
- logClient.error(`Auth (${SDK_VERSION$1}): ${msg}`, ...args);
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _fail(authOrCode, ...rest) {
- throw createErrorInternal(authOrCode, ...rest);
- }
- function _createError(authOrCode, ...rest) {
- return createErrorInternal(authOrCode, ...rest);
- }
- function _errorWithCustomMessage(auth, code, message) {
- const errorMap = Object.assign(Object.assign({}, prodErrorMap()), { [code]: message });
- const factory = new ErrorFactory('auth', 'Firebase', errorMap);
- return factory.create(code, {
- appName: auth.name
- });
- }
- function _assertInstanceOf(auth, object, instance) {
- const constructorInstance = instance;
- if (!(object instanceof constructorInstance)) {
- if (constructorInstance.name !== object.constructor.name) {
- _fail(auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- }
- throw _errorWithCustomMessage(auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */, `Type of ${object.constructor.name} does not match expected instance.` +
- `Did you pass a reference from a different Auth SDK?`);
- }
- }
- function createErrorInternal(authOrCode, ...rest) {
- if (typeof authOrCode !== 'string') {
- const code = rest[0];
- const fullParams = [...rest.slice(1)];
- if (fullParams[0]) {
- fullParams[0].appName = authOrCode.name;
- }
- return authOrCode._errorFactory.create(code, ...fullParams);
- }
- return _DEFAULT_AUTH_ERROR_FACTORY.create(authOrCode, ...rest);
- }
- function _assert$4(assertion, authOrCode, ...rest) {
- if (!assertion) {
- throw createErrorInternal(authOrCode, ...rest);
- }
- }
- /**
- * Unconditionally fails, throwing an internal error with the given message.
- *
- * @param failure type of failure encountered
- * @throws Error
- */
- function debugFail(failure) {
- // Log the failure in addition to throw an exception, just in case the
- // exception is swallowed.
- const message = `INTERNAL ASSERTION FAILED: ` + failure;
- _logError(message);
- // NOTE: We don't use FirebaseError here because these are internal failures
- // that cannot be handled by the user. (Also it would create a circular
- // dependency between the error and assert modules which doesn't work.)
- throw new Error(message);
- }
- /**
- * Fails if the given assertion condition is false, throwing an Error with the
- * given message if it did.
- *
- * @param assertion
- * @param message
- */
- function debugAssert(assertion, message) {
- if (!assertion) {
- debugFail(message);
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _getCurrentUrl() {
- var _a;
- return (typeof self !== 'undefined' && ((_a = self.location) === null || _a === void 0 ? void 0 : _a.href)) || '';
- }
- function _isHttpOrHttps$1() {
- return _getCurrentScheme$1() === 'http:' || _getCurrentScheme$1() === 'https:';
- }
- function _getCurrentScheme$1() {
- var _a;
- return (typeof self !== 'undefined' && ((_a = self.location) === null || _a === void 0 ? void 0 : _a.protocol)) || null;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Determine whether the browser is working online
- */
- function _isOnline() {
- if (typeof navigator !== 'undefined' &&
- navigator &&
- 'onLine' in navigator &&
- typeof navigator.onLine === 'boolean' &&
- // Apply only for traditional web apps and Chrome extensions.
- // This is especially true for Cordova apps which have unreliable
- // navigator.onLine behavior unless cordova-plugin-network-information is
- // installed which overwrites the native navigator.onLine value and
- // defines navigator.connection.
- (_isHttpOrHttps$1() || isBrowserExtension() || 'connection' in navigator)) {
- return navigator.onLine;
- }
- // If we can't determine the state, assume it is online.
- return true;
- }
- function _getUserLanguage() {
- if (typeof navigator === 'undefined') {
- return null;
- }
- const navigatorLanguage = navigator;
- return (
- // Most reliable, but only supported in Chrome/Firefox.
- (navigatorLanguage.languages && navigatorLanguage.languages[0]) ||
- // Supported in most browsers, but returns the language of the browser
- // UI, not the language set in browser settings.
- navigatorLanguage.language ||
- // Couldn't determine language.
- null);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * A structure to help pick between a range of long and short delay durations
- * depending on the current environment. In general, the long delay is used for
- * mobile environments whereas short delays are used for desktop environments.
- */
- class Delay {
- constructor(shortDelay, longDelay) {
- this.shortDelay = shortDelay;
- this.longDelay = longDelay;
- // Internal error when improperly initialized.
- debugAssert(longDelay > shortDelay, 'Short delay should be less than long delay!');
- this.isMobile = isMobileCordova() || isReactNative();
- }
- get() {
- if (!_isOnline()) {
- // Pick the shorter timeout.
- return Math.min(5000 /* DelayMin.OFFLINE */, this.shortDelay);
- }
- // If running in a mobile environment, return the long delay, otherwise
- // return the short delay.
- // This could be improved in the future to dynamically change based on other
- // variables instead of just reading the current environment.
- return this.isMobile ? this.longDelay : this.shortDelay;
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _emulatorUrl(config, path) {
- debugAssert(config.emulator, 'Emulator should always be set here');
- const { url } = config.emulator;
- if (!path) {
- return url;
- }
- return `${url}${path.startsWith('/') ? path.slice(1) : path}`;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class FetchProvider {
- static initialize(fetchImpl, headersImpl, responseImpl) {
- this.fetchImpl = fetchImpl;
- if (headersImpl) {
- this.headersImpl = headersImpl;
- }
- if (responseImpl) {
- this.responseImpl = responseImpl;
- }
- }
- static fetch() {
- if (this.fetchImpl) {
- return this.fetchImpl;
- }
- if (typeof self !== 'undefined' && 'fetch' in self) {
- return self.fetch;
- }
- debugFail('Could not find fetch implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
- }
- static headers() {
- if (this.headersImpl) {
- return this.headersImpl;
- }
- if (typeof self !== 'undefined' && 'Headers' in self) {
- return self.Headers;
- }
- debugFail('Could not find Headers implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
- }
- static response() {
- if (this.responseImpl) {
- return this.responseImpl;
- }
- if (typeof self !== 'undefined' && 'Response' in self) {
- return self.Response;
- }
- debugFail('Could not find Response implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill');
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Map from errors returned by the server to errors to developer visible errors
- */
- const SERVER_ERROR_MAP = {
- // Custom token errors.
- ["CREDENTIAL_MISMATCH" /* ServerError.CREDENTIAL_MISMATCH */]: "custom-token-mismatch" /* AuthErrorCode.CREDENTIAL_MISMATCH */,
- // This can only happen if the SDK sends a bad request.
- ["MISSING_CUSTOM_TOKEN" /* ServerError.MISSING_CUSTOM_TOKEN */]: "internal-error" /* AuthErrorCode.INTERNAL_ERROR */,
- // Create Auth URI errors.
- ["INVALID_IDENTIFIER" /* ServerError.INVALID_IDENTIFIER */]: "invalid-email" /* AuthErrorCode.INVALID_EMAIL */,
- // This can only happen if the SDK sends a bad request.
- ["MISSING_CONTINUE_URI" /* ServerError.MISSING_CONTINUE_URI */]: "internal-error" /* AuthErrorCode.INTERNAL_ERROR */,
- // Sign in with email and password errors (some apply to sign up too).
- ["INVALID_PASSWORD" /* ServerError.INVALID_PASSWORD */]: "wrong-password" /* AuthErrorCode.INVALID_PASSWORD */,
- // This can only happen if the SDK sends a bad request.
- ["MISSING_PASSWORD" /* ServerError.MISSING_PASSWORD */]: "missing-password" /* AuthErrorCode.MISSING_PASSWORD */,
- // Sign up with email and password errors.
- ["EMAIL_EXISTS" /* ServerError.EMAIL_EXISTS */]: "email-already-in-use" /* AuthErrorCode.EMAIL_EXISTS */,
- ["PASSWORD_LOGIN_DISABLED" /* ServerError.PASSWORD_LOGIN_DISABLED */]: "operation-not-allowed" /* AuthErrorCode.OPERATION_NOT_ALLOWED */,
- // Verify assertion for sign in with credential errors:
- ["INVALID_IDP_RESPONSE" /* ServerError.INVALID_IDP_RESPONSE */]: "invalid-credential" /* AuthErrorCode.INVALID_IDP_RESPONSE */,
- ["INVALID_PENDING_TOKEN" /* ServerError.INVALID_PENDING_TOKEN */]: "invalid-credential" /* AuthErrorCode.INVALID_IDP_RESPONSE */,
- ["FEDERATED_USER_ID_ALREADY_LINKED" /* ServerError.FEDERATED_USER_ID_ALREADY_LINKED */]: "credential-already-in-use" /* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */,
- // This can only happen if the SDK sends a bad request.
- ["MISSING_REQ_TYPE" /* ServerError.MISSING_REQ_TYPE */]: "internal-error" /* AuthErrorCode.INTERNAL_ERROR */,
- // Send Password reset email errors:
- ["EMAIL_NOT_FOUND" /* ServerError.EMAIL_NOT_FOUND */]: "user-not-found" /* AuthErrorCode.USER_DELETED */,
- ["RESET_PASSWORD_EXCEED_LIMIT" /* ServerError.RESET_PASSWORD_EXCEED_LIMIT */]: "too-many-requests" /* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */,
- ["EXPIRED_OOB_CODE" /* ServerError.EXPIRED_OOB_CODE */]: "expired-action-code" /* AuthErrorCode.EXPIRED_OOB_CODE */,
- ["INVALID_OOB_CODE" /* ServerError.INVALID_OOB_CODE */]: "invalid-action-code" /* AuthErrorCode.INVALID_OOB_CODE */,
- // This can only happen if the SDK sends a bad request.
- ["MISSING_OOB_CODE" /* ServerError.MISSING_OOB_CODE */]: "internal-error" /* AuthErrorCode.INTERNAL_ERROR */,
- // Operations that require ID token in request:
- ["CREDENTIAL_TOO_OLD_LOGIN_AGAIN" /* ServerError.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */]: "requires-recent-login" /* AuthErrorCode.CREDENTIAL_TOO_OLD_LOGIN_AGAIN */,
- ["INVALID_ID_TOKEN" /* ServerError.INVALID_ID_TOKEN */]: "invalid-user-token" /* AuthErrorCode.INVALID_AUTH */,
- ["TOKEN_EXPIRED" /* ServerError.TOKEN_EXPIRED */]: "user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */,
- ["USER_NOT_FOUND" /* ServerError.USER_NOT_FOUND */]: "user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */,
- // Other errors.
- ["TOO_MANY_ATTEMPTS_TRY_LATER" /* ServerError.TOO_MANY_ATTEMPTS_TRY_LATER */]: "too-many-requests" /* AuthErrorCode.TOO_MANY_ATTEMPTS_TRY_LATER */,
- // Phone Auth related errors.
- ["INVALID_CODE" /* ServerError.INVALID_CODE */]: "invalid-verification-code" /* AuthErrorCode.INVALID_CODE */,
- ["INVALID_SESSION_INFO" /* ServerError.INVALID_SESSION_INFO */]: "invalid-verification-id" /* AuthErrorCode.INVALID_SESSION_INFO */,
- ["INVALID_TEMPORARY_PROOF" /* ServerError.INVALID_TEMPORARY_PROOF */]: "invalid-credential" /* AuthErrorCode.INVALID_IDP_RESPONSE */,
- ["MISSING_SESSION_INFO" /* ServerError.MISSING_SESSION_INFO */]: "missing-verification-id" /* AuthErrorCode.MISSING_SESSION_INFO */,
- ["SESSION_EXPIRED" /* ServerError.SESSION_EXPIRED */]: "code-expired" /* AuthErrorCode.CODE_EXPIRED */,
- // Other action code errors when additional settings passed.
- // MISSING_CONTINUE_URI is getting mapped to INTERNAL_ERROR above.
- // This is OK as this error will be caught by client side validation.
- ["MISSING_ANDROID_PACKAGE_NAME" /* ServerError.MISSING_ANDROID_PACKAGE_NAME */]: "missing-android-pkg-name" /* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */,
- ["UNAUTHORIZED_DOMAIN" /* ServerError.UNAUTHORIZED_DOMAIN */]: "unauthorized-continue-uri" /* AuthErrorCode.UNAUTHORIZED_DOMAIN */,
- // getProjectConfig errors when clientId is passed.
- ["INVALID_OAUTH_CLIENT_ID" /* ServerError.INVALID_OAUTH_CLIENT_ID */]: "invalid-oauth-client-id" /* AuthErrorCode.INVALID_OAUTH_CLIENT_ID */,
- // User actions (sign-up or deletion) disabled errors.
- ["ADMIN_ONLY_OPERATION" /* ServerError.ADMIN_ONLY_OPERATION */]: "admin-restricted-operation" /* AuthErrorCode.ADMIN_ONLY_OPERATION */,
- // Multi factor related errors.
- ["INVALID_MFA_PENDING_CREDENTIAL" /* ServerError.INVALID_MFA_PENDING_CREDENTIAL */]: "invalid-multi-factor-session" /* AuthErrorCode.INVALID_MFA_SESSION */,
- ["MFA_ENROLLMENT_NOT_FOUND" /* ServerError.MFA_ENROLLMENT_NOT_FOUND */]: "multi-factor-info-not-found" /* AuthErrorCode.MFA_INFO_NOT_FOUND */,
- ["MISSING_MFA_ENROLLMENT_ID" /* ServerError.MISSING_MFA_ENROLLMENT_ID */]: "missing-multi-factor-info" /* AuthErrorCode.MISSING_MFA_INFO */,
- ["MISSING_MFA_PENDING_CREDENTIAL" /* ServerError.MISSING_MFA_PENDING_CREDENTIAL */]: "missing-multi-factor-session" /* AuthErrorCode.MISSING_MFA_SESSION */,
- ["SECOND_FACTOR_EXISTS" /* ServerError.SECOND_FACTOR_EXISTS */]: "second-factor-already-in-use" /* AuthErrorCode.SECOND_FACTOR_ALREADY_ENROLLED */,
- ["SECOND_FACTOR_LIMIT_EXCEEDED" /* ServerError.SECOND_FACTOR_LIMIT_EXCEEDED */]: "maximum-second-factor-count-exceeded" /* AuthErrorCode.SECOND_FACTOR_LIMIT_EXCEEDED */,
- // Blocking functions related errors.
- ["BLOCKING_FUNCTION_ERROR_RESPONSE" /* ServerError.BLOCKING_FUNCTION_ERROR_RESPONSE */]: "internal-error" /* AuthErrorCode.INTERNAL_ERROR */,
- // Recaptcha related errors.
- ["RECAPTCHA_NOT_ENABLED" /* ServerError.RECAPTCHA_NOT_ENABLED */]: "recaptcha-not-enabled" /* AuthErrorCode.RECAPTCHA_NOT_ENABLED */,
- ["MISSING_RECAPTCHA_TOKEN" /* ServerError.MISSING_RECAPTCHA_TOKEN */]: "missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */,
- ["INVALID_RECAPTCHA_TOKEN" /* ServerError.INVALID_RECAPTCHA_TOKEN */]: "invalid-recaptcha-token" /* AuthErrorCode.INVALID_RECAPTCHA_TOKEN */,
- ["INVALID_RECAPTCHA_ACTION" /* ServerError.INVALID_RECAPTCHA_ACTION */]: "invalid-recaptcha-action" /* AuthErrorCode.INVALID_RECAPTCHA_ACTION */,
- ["MISSING_CLIENT_TYPE" /* ServerError.MISSING_CLIENT_TYPE */]: "missing-client-type" /* AuthErrorCode.MISSING_CLIENT_TYPE */,
- ["MISSING_RECAPTCHA_VERSION" /* ServerError.MISSING_RECAPTCHA_VERSION */]: "missing-recaptcha-version" /* AuthErrorCode.MISSING_RECAPTCHA_VERSION */,
- ["INVALID_RECAPTCHA_VERSION" /* ServerError.INVALID_RECAPTCHA_VERSION */]: "invalid-recaptcha-version" /* AuthErrorCode.INVALID_RECAPTCHA_VERSION */,
- ["INVALID_REQ_TYPE" /* ServerError.INVALID_REQ_TYPE */]: "invalid-req-type" /* AuthErrorCode.INVALID_REQ_TYPE */
- };
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const DEFAULT_API_TIMEOUT_MS = new Delay(30000, 60000);
- function _addTidIfNecessary(auth, request) {
- if (auth.tenantId && !request.tenantId) {
- return Object.assign(Object.assign({}, request), { tenantId: auth.tenantId });
- }
- return request;
- }
- async function _performApiRequest(auth, method, path, request, customErrorMap = {}) {
- return _performFetchWithErrorHandling(auth, customErrorMap, async () => {
- let body = {};
- let params = {};
- if (request) {
- if (method === "GET" /* HttpMethod.GET */) {
- params = request;
- }
- else {
- body = {
- body: JSON.stringify(request)
- };
- }
- }
- const query = querystring(Object.assign({ key: auth.config.apiKey }, params)).slice(1);
- const headers = await auth._getAdditionalHeaders();
- headers["Content-Type" /* HttpHeader.CONTENT_TYPE */] = 'application/json';
- if (auth.languageCode) {
- headers["X-Firebase-Locale" /* HttpHeader.X_FIREBASE_LOCALE */] = auth.languageCode;
- }
- return FetchProvider.fetch()(_getFinalTarget(auth, auth.config.apiHost, path, query), Object.assign({ method,
- headers, referrerPolicy: 'no-referrer' }, body));
- });
- }
- async function _performFetchWithErrorHandling(auth, customErrorMap, fetchFn) {
- auth._canInitEmulator = false;
- const errorMap = Object.assign(Object.assign({}, SERVER_ERROR_MAP), customErrorMap);
- try {
- const networkTimeout = new NetworkTimeout(auth);
- const response = await Promise.race([
- fetchFn(),
- networkTimeout.promise
- ]);
- // If we've reached this point, the fetch succeeded and the networkTimeout
- // didn't throw; clear the network timeout delay so that Node won't hang
- networkTimeout.clearNetworkTimeout();
- const json = await response.json();
- if ('needConfirmation' in json) {
- throw _makeTaggedError(auth, "account-exists-with-different-credential" /* AuthErrorCode.NEED_CONFIRMATION */, json);
- }
- if (response.ok && !('errorMessage' in json)) {
- return json;
- }
- else {
- const errorMessage = response.ok ? json.errorMessage : json.error.message;
- const [serverErrorCode, serverErrorMessage] = errorMessage.split(' : ');
- if (serverErrorCode === "FEDERATED_USER_ID_ALREADY_LINKED" /* ServerError.FEDERATED_USER_ID_ALREADY_LINKED */) {
- throw _makeTaggedError(auth, "credential-already-in-use" /* AuthErrorCode.CREDENTIAL_ALREADY_IN_USE */, json);
- }
- else if (serverErrorCode === "EMAIL_EXISTS" /* ServerError.EMAIL_EXISTS */) {
- throw _makeTaggedError(auth, "email-already-in-use" /* AuthErrorCode.EMAIL_EXISTS */, json);
- }
- else if (serverErrorCode === "USER_DISABLED" /* ServerError.USER_DISABLED */) {
- throw _makeTaggedError(auth, "user-disabled" /* AuthErrorCode.USER_DISABLED */, json);
- }
- const authError = errorMap[serverErrorCode] ||
- serverErrorCode
- .toLowerCase()
- .replace(/[_\s]+/g, '-');
- if (serverErrorMessage) {
- throw _errorWithCustomMessage(auth, authError, serverErrorMessage);
- }
- else {
- _fail(auth, authError);
- }
- }
- }
- catch (e) {
- if (e instanceof FirebaseError) {
- throw e;
- }
- // Changing this to a different error code will log user out when there is a network error
- // because we treat any error other than NETWORK_REQUEST_FAILED as token is invalid.
- // https://github.com/firebase/firebase-js-sdk/blob/4fbc73610d70be4e0852e7de63a39cb7897e8546/packages/auth/src/core/auth/auth_impl.ts#L309-L316
- _fail(auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */, { 'message': String(e) });
- }
- }
- async function _performSignInRequest(auth, method, path, request, customErrorMap = {}) {
- const serverResponse = (await _performApiRequest(auth, method, path, request, customErrorMap));
- if ('mfaPendingCredential' in serverResponse) {
- _fail(auth, "multi-factor-auth-required" /* AuthErrorCode.MFA_REQUIRED */, {
- _serverResponse: serverResponse
- });
- }
- return serverResponse;
- }
- function _getFinalTarget(auth, host, path, query) {
- const base = `${host}${path}?${query}`;
- if (!auth.config.emulator) {
- return `${auth.config.apiScheme}://${base}`;
- }
- return _emulatorUrl(auth.config, base);
- }
- class NetworkTimeout {
- constructor(auth) {
- this.auth = auth;
- // Node timers and browser timers are fundamentally incompatible, but we
- // don't care about the value here
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- this.timer = null;
- this.promise = new Promise((_, reject) => {
- this.timer = setTimeout(() => {
- return reject(_createError(this.auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */));
- }, DEFAULT_API_TIMEOUT_MS.get());
- });
- }
- clearNetworkTimeout() {
- clearTimeout(this.timer);
- }
- }
- function _makeTaggedError(auth, code, response) {
- const errorParams = {
- appName: auth.name
- };
- if (response.email) {
- errorParams.email = response.email;
- }
- if (response.phoneNumber) {
- errorParams.phoneNumber = response.phoneNumber;
- }
- const error = _createError(auth, code, errorParams);
- // We know customData is defined on error because errorParams is defined
- error.customData._tokenResponse = response;
- return error;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function deleteAccount(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:delete" /* Endpoint.DELETE_ACCOUNT */, request);
- }
- async function deleteLinkedAccounts(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:update" /* Endpoint.SET_ACCOUNT_INFO */, request);
- }
- async function getAccountInfo(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:lookup" /* Endpoint.GET_ACCOUNT_INFO */, request);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function utcTimestampToDateString(utcTimestamp) {
- if (!utcTimestamp) {
- return undefined;
- }
- try {
- // Convert to date object.
- const date = new Date(Number(utcTimestamp));
- // Test date is valid.
- if (!isNaN(date.getTime())) {
- // Convert to UTC date string.
- return date.toUTCString();
- }
- }
- catch (e) {
- // Do nothing. undefined will be returned.
- }
- return undefined;
- }
- /**
- * Returns a deserialized JSON Web Token (JWT) used to identify the user to a Firebase service.
- *
- * @remarks
- * Returns the current token if it has not expired or if it will not expire in the next five
- * minutes. Otherwise, this will refresh the token and return a new one.
- *
- * @param user - The user.
- * @param forceRefresh - Force refresh regardless of token expiration.
- *
- * @public
- */
- async function getIdTokenResult(user, forceRefresh = false) {
- const userInternal = getModularInstance(user);
- const token = await userInternal.getIdToken(forceRefresh);
- const claims = _parseToken(token);
- _assert$4(claims && claims.exp && claims.auth_time && claims.iat, userInternal.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const firebase = typeof claims.firebase === 'object' ? claims.firebase : undefined;
- const signInProvider = firebase === null || firebase === void 0 ? void 0 : firebase['sign_in_provider'];
- return {
- claims,
- token,
- authTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.auth_time)),
- issuedAtTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.iat)),
- expirationTime: utcTimestampToDateString(secondsStringToMilliseconds(claims.exp)),
- signInProvider: signInProvider || null,
- signInSecondFactor: (firebase === null || firebase === void 0 ? void 0 : firebase['sign_in_second_factor']) || null
- };
- }
- function secondsStringToMilliseconds(seconds) {
- return Number(seconds) * 1000;
- }
- function _parseToken(token) {
- const [algorithm, payload, signature] = token.split('.');
- if (algorithm === undefined ||
- payload === undefined ||
- signature === undefined) {
- _logError('JWT malformed, contained fewer than 3 sections');
- return null;
- }
- try {
- const decoded = base64Decode(payload);
- if (!decoded) {
- _logError('Failed to decode base64 JWT payload');
- return null;
- }
- return JSON.parse(decoded);
- }
- catch (e) {
- _logError('Caught error parsing JWT payload as JSON', e === null || e === void 0 ? void 0 : e.toString());
- return null;
- }
- }
- /**
- * Extract expiresIn TTL from a token by subtracting the expiration from the issuance.
- */
- function _tokenExpiresIn(token) {
- const parsedToken = _parseToken(token);
- _assert$4(parsedToken, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- _assert$4(typeof parsedToken.exp !== 'undefined', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- _assert$4(typeof parsedToken.iat !== 'undefined', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return Number(parsedToken.exp) - Number(parsedToken.iat);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function _logoutIfInvalidated(user, promise, bypassAuthState = false) {
- if (bypassAuthState) {
- return promise;
- }
- try {
- return await promise;
- }
- catch (e) {
- if (e instanceof FirebaseError && isUserInvalidated(e)) {
- if (user.auth.currentUser === user) {
- await user.auth.signOut();
- }
- }
- throw e;
- }
- }
- function isUserInvalidated({ code }) {
- return (code === `auth/${"user-disabled" /* AuthErrorCode.USER_DISABLED */}` ||
- code === `auth/${"user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */}`);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class ProactiveRefresh {
- constructor(user) {
- this.user = user;
- this.isRunning = false;
- // Node timers and browser timers return fundamentally different types.
- // We don't actually care what the value is but TS won't accept unknown and
- // we can't cast properly in both environments.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- this.timerId = null;
- this.errorBackoff = 30000 /* Duration.RETRY_BACKOFF_MIN */;
- }
- _start() {
- if (this.isRunning) {
- return;
- }
- this.isRunning = true;
- this.schedule();
- }
- _stop() {
- if (!this.isRunning) {
- return;
- }
- this.isRunning = false;
- if (this.timerId !== null) {
- clearTimeout(this.timerId);
- }
- }
- getInterval(wasError) {
- var _a;
- if (wasError) {
- const interval = this.errorBackoff;
- this.errorBackoff = Math.min(this.errorBackoff * 2, 960000 /* Duration.RETRY_BACKOFF_MAX */);
- return interval;
- }
- else {
- // Reset the error backoff
- this.errorBackoff = 30000 /* Duration.RETRY_BACKOFF_MIN */;
- const expTime = (_a = this.user.stsTokenManager.expirationTime) !== null && _a !== void 0 ? _a : 0;
- const interval = expTime - Date.now() - 300000 /* Duration.OFFSET */;
- return Math.max(0, interval);
- }
- }
- schedule(wasError = false) {
- if (!this.isRunning) {
- // Just in case...
- return;
- }
- const interval = this.getInterval(wasError);
- this.timerId = setTimeout(async () => {
- await this.iteration();
- }, interval);
- }
- async iteration() {
- try {
- await this.user.getIdToken(true);
- }
- catch (e) {
- // Only retry on network errors
- if ((e === null || e === void 0 ? void 0 : e.code) ===
- `auth/${"network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */}`) {
- this.schedule(/* wasError */ true);
- }
- return;
- }
- this.schedule();
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class UserMetadata {
- constructor(createdAt, lastLoginAt) {
- this.createdAt = createdAt;
- this.lastLoginAt = lastLoginAt;
- this._initializeTime();
- }
- _initializeTime() {
- this.lastSignInTime = utcTimestampToDateString(this.lastLoginAt);
- this.creationTime = utcTimestampToDateString(this.createdAt);
- }
- _copy(metadata) {
- this.createdAt = metadata.createdAt;
- this.lastLoginAt = metadata.lastLoginAt;
- this._initializeTime();
- }
- toJSON() {
- return {
- createdAt: this.createdAt,
- lastLoginAt: this.lastLoginAt
- };
- }
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function _reloadWithoutSaving(user) {
- var _a;
- const auth = user.auth;
- const idToken = await user.getIdToken();
- const response = await _logoutIfInvalidated(user, getAccountInfo(auth, { idToken }));
- _assert$4(response === null || response === void 0 ? void 0 : response.users.length, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const coreAccount = response.users[0];
- user._notifyReloadListener(coreAccount);
- const newProviderData = ((_a = coreAccount.providerUserInfo) === null || _a === void 0 ? void 0 : _a.length)
- ? extractProviderData(coreAccount.providerUserInfo)
- : [];
- const providerData = mergeProviderData(user.providerData, newProviderData);
- // Preserves the non-nonymous status of the stored user, even if no more
- // credentials (federated or email/password) are linked to the user. If
- // the user was previously anonymous, then use provider data to update.
- // On the other hand, if it was not anonymous before, it should never be
- // considered anonymous now.
- const oldIsAnonymous = user.isAnonymous;
- const newIsAnonymous = !(user.email && coreAccount.passwordHash) && !(providerData === null || providerData === void 0 ? void 0 : providerData.length);
- const isAnonymous = !oldIsAnonymous ? false : newIsAnonymous;
- const updates = {
- uid: coreAccount.localId,
- displayName: coreAccount.displayName || null,
- photoURL: coreAccount.photoUrl || null,
- email: coreAccount.email || null,
- emailVerified: coreAccount.emailVerified || false,
- phoneNumber: coreAccount.phoneNumber || null,
- tenantId: coreAccount.tenantId || null,
- providerData,
- metadata: new UserMetadata(coreAccount.createdAt, coreAccount.lastLoginAt),
- isAnonymous
- };
- Object.assign(user, updates);
- }
- /**
- * Reloads user account data, if signed in.
- *
- * @param user - The user.
- *
- * @public
- */
- async function reload(user) {
- const userInternal = getModularInstance(user);
- await _reloadWithoutSaving(userInternal);
- // Even though the current user hasn't changed, update
- // current user will trigger a persistence update w/ the
- // new info.
- await userInternal.auth._persistUserIfCurrent(userInternal);
- userInternal.auth._notifyListenersIfCurrent(userInternal);
- }
- function mergeProviderData(original, newData) {
- const deduped = original.filter(o => !newData.some(n => n.providerId === o.providerId));
- return [...deduped, ...newData];
- }
- function extractProviderData(providers) {
- return providers.map((_a) => {
- var { providerId } = _a, provider = __rest(_a, ["providerId"]);
- return {
- providerId,
- uid: provider.rawId || '',
- displayName: provider.displayName || null,
- email: provider.email || null,
- phoneNumber: provider.phoneNumber || null,
- photoURL: provider.photoUrl || null
- };
- });
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function requestStsToken(auth, refreshToken) {
- const response = await _performFetchWithErrorHandling(auth, {}, async () => {
- const body = querystring({
- 'grant_type': 'refresh_token',
- 'refresh_token': refreshToken
- }).slice(1);
- const { tokenApiHost, apiKey } = auth.config;
- const url = _getFinalTarget(auth, tokenApiHost, "/v1/token" /* Endpoint.TOKEN */, `key=${apiKey}`);
- const headers = await auth._getAdditionalHeaders();
- headers["Content-Type" /* HttpHeader.CONTENT_TYPE */] = 'application/x-www-form-urlencoded';
- return FetchProvider.fetch()(url, {
- method: "POST" /* HttpMethod.POST */,
- headers,
- body
- });
- });
- // The response comes back in snake_case. Convert to camel:
- return {
- accessToken: response.access_token,
- expiresIn: response.expires_in,
- refreshToken: response.refresh_token
- };
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * We need to mark this class as internal explicitly to exclude it in the public typings, because
- * it references AuthInternal which has a circular dependency with UserInternal.
- *
- * @internal
- */
- class StsTokenManager {
- constructor() {
- this.refreshToken = null;
- this.accessToken = null;
- this.expirationTime = null;
- }
- get isExpired() {
- return (!this.expirationTime ||
- Date.now() > this.expirationTime - 30000 /* Buffer.TOKEN_REFRESH */);
- }
- updateFromServerResponse(response) {
- _assert$4(response.idToken, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- _assert$4(typeof response.idToken !== 'undefined', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- _assert$4(typeof response.refreshToken !== 'undefined', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const expiresIn = 'expiresIn' in response && typeof response.expiresIn !== 'undefined'
- ? Number(response.expiresIn)
- : _tokenExpiresIn(response.idToken);
- this.updateTokensAndExpiration(response.idToken, response.refreshToken, expiresIn);
- }
- async getToken(auth, forceRefresh = false) {
- _assert$4(!this.accessToken || this.refreshToken, auth, "user-token-expired" /* AuthErrorCode.TOKEN_EXPIRED */);
- if (!forceRefresh && this.accessToken && !this.isExpired) {
- return this.accessToken;
- }
- if (this.refreshToken) {
- await this.refresh(auth, this.refreshToken);
- return this.accessToken;
- }
- return null;
- }
- clearRefreshToken() {
- this.refreshToken = null;
- }
- async refresh(auth, oldToken) {
- const { accessToken, refreshToken, expiresIn } = await requestStsToken(auth, oldToken);
- this.updateTokensAndExpiration(accessToken, refreshToken, Number(expiresIn));
- }
- updateTokensAndExpiration(accessToken, refreshToken, expiresInSec) {
- this.refreshToken = refreshToken || null;
- this.accessToken = accessToken || null;
- this.expirationTime = Date.now() + expiresInSec * 1000;
- }
- static fromJSON(appName, object) {
- const { refreshToken, accessToken, expirationTime } = object;
- const manager = new StsTokenManager();
- if (refreshToken) {
- _assert$4(typeof refreshToken === 'string', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */, {
- appName
- });
- manager.refreshToken = refreshToken;
- }
- if (accessToken) {
- _assert$4(typeof accessToken === 'string', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */, {
- appName
- });
- manager.accessToken = accessToken;
- }
- if (expirationTime) {
- _assert$4(typeof expirationTime === 'number', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */, {
- appName
- });
- manager.expirationTime = expirationTime;
- }
- return manager;
- }
- toJSON() {
- return {
- refreshToken: this.refreshToken,
- accessToken: this.accessToken,
- expirationTime: this.expirationTime
- };
- }
- _assign(stsTokenManager) {
- this.accessToken = stsTokenManager.accessToken;
- this.refreshToken = stsTokenManager.refreshToken;
- this.expirationTime = stsTokenManager.expirationTime;
- }
- _clone() {
- return Object.assign(new StsTokenManager(), this.toJSON());
- }
- _performRefresh() {
- return debugFail('not implemented');
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function assertStringOrUndefined(assertion, appName) {
- _assert$4(typeof assertion === 'string' || typeof assertion === 'undefined', "internal-error" /* AuthErrorCode.INTERNAL_ERROR */, { appName });
- }
- class UserImpl {
- constructor(_a) {
- var { uid, auth, stsTokenManager } = _a, opt = __rest(_a, ["uid", "auth", "stsTokenManager"]);
- // For the user object, provider is always Firebase.
- this.providerId = "firebase" /* ProviderId.FIREBASE */;
- this.proactiveRefresh = new ProactiveRefresh(this);
- this.reloadUserInfo = null;
- this.reloadListener = null;
- this.uid = uid;
- this.auth = auth;
- this.stsTokenManager = stsTokenManager;
- this.accessToken = stsTokenManager.accessToken;
- this.displayName = opt.displayName || null;
- this.email = opt.email || null;
- this.emailVerified = opt.emailVerified || false;
- this.phoneNumber = opt.phoneNumber || null;
- this.photoURL = opt.photoURL || null;
- this.isAnonymous = opt.isAnonymous || false;
- this.tenantId = opt.tenantId || null;
- this.providerData = opt.providerData ? [...opt.providerData] : [];
- this.metadata = new UserMetadata(opt.createdAt || undefined, opt.lastLoginAt || undefined);
- }
- async getIdToken(forceRefresh) {
- const accessToken = await _logoutIfInvalidated(this, this.stsTokenManager.getToken(this.auth, forceRefresh));
- _assert$4(accessToken, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- if (this.accessToken !== accessToken) {
- this.accessToken = accessToken;
- await this.auth._persistUserIfCurrent(this);
- this.auth._notifyListenersIfCurrent(this);
- }
- return accessToken;
- }
- getIdTokenResult(forceRefresh) {
- return getIdTokenResult(this, forceRefresh);
- }
- reload() {
- return reload(this);
- }
- _assign(user) {
- if (this === user) {
- return;
- }
- _assert$4(this.uid === user.uid, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- this.displayName = user.displayName;
- this.photoURL = user.photoURL;
- this.email = user.email;
- this.emailVerified = user.emailVerified;
- this.phoneNumber = user.phoneNumber;
- this.isAnonymous = user.isAnonymous;
- this.tenantId = user.tenantId;
- this.providerData = user.providerData.map(userInfo => (Object.assign({}, userInfo)));
- this.metadata._copy(user.metadata);
- this.stsTokenManager._assign(user.stsTokenManager);
- }
- _clone(auth) {
- const newUser = new UserImpl(Object.assign(Object.assign({}, this), { auth, stsTokenManager: this.stsTokenManager._clone() }));
- newUser.metadata._copy(this.metadata);
- return newUser;
- }
- _onReload(callback) {
- // There should only ever be one listener, and that is a single instance of MultiFactorUser
- _assert$4(!this.reloadListener, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- this.reloadListener = callback;
- if (this.reloadUserInfo) {
- this._notifyReloadListener(this.reloadUserInfo);
- this.reloadUserInfo = null;
- }
- }
- _notifyReloadListener(userInfo) {
- if (this.reloadListener) {
- this.reloadListener(userInfo);
- }
- else {
- // If no listener is subscribed yet, save the result so it's available when they do subscribe
- this.reloadUserInfo = userInfo;
- }
- }
- _startProactiveRefresh() {
- this.proactiveRefresh._start();
- }
- _stopProactiveRefresh() {
- this.proactiveRefresh._stop();
- }
- async _updateTokensIfNecessary(response, reload = false) {
- let tokensRefreshed = false;
- if (response.idToken &&
- response.idToken !== this.stsTokenManager.accessToken) {
- this.stsTokenManager.updateFromServerResponse(response);
- tokensRefreshed = true;
- }
- if (reload) {
- await _reloadWithoutSaving(this);
- }
- await this.auth._persistUserIfCurrent(this);
- if (tokensRefreshed) {
- this.auth._notifyListenersIfCurrent(this);
- }
- }
- async delete() {
- const idToken = await this.getIdToken();
- await _logoutIfInvalidated(this, deleteAccount(this.auth, { idToken }));
- this.stsTokenManager.clearRefreshToken();
- // TODO: Determine if cancellable-promises are necessary to use in this class so that delete()
- // cancels pending actions...
- return this.auth.signOut();
- }
- toJSON() {
- return Object.assign(Object.assign({ uid: this.uid, email: this.email || undefined, emailVerified: this.emailVerified, displayName: this.displayName || undefined, isAnonymous: this.isAnonymous, photoURL: this.photoURL || undefined, phoneNumber: this.phoneNumber || undefined, tenantId: this.tenantId || undefined, providerData: this.providerData.map(userInfo => (Object.assign({}, userInfo))), stsTokenManager: this.stsTokenManager.toJSON(),
- // Redirect event ID must be maintained in case there is a pending
- // redirect event.
- _redirectEventId: this._redirectEventId }, this.metadata.toJSON()), {
- // Required for compatibility with the legacy SDK (go/firebase-auth-sdk-persistence-parsing):
- apiKey: this.auth.config.apiKey, appName: this.auth.name });
- }
- get refreshToken() {
- return this.stsTokenManager.refreshToken || '';
- }
- static _fromJSON(auth, object) {
- var _a, _b, _c, _d, _e, _f, _g, _h;
- const displayName = (_a = object.displayName) !== null && _a !== void 0 ? _a : undefined;
- const email = (_b = object.email) !== null && _b !== void 0 ? _b : undefined;
- const phoneNumber = (_c = object.phoneNumber) !== null && _c !== void 0 ? _c : undefined;
- const photoURL = (_d = object.photoURL) !== null && _d !== void 0 ? _d : undefined;
- const tenantId = (_e = object.tenantId) !== null && _e !== void 0 ? _e : undefined;
- const _redirectEventId = (_f = object._redirectEventId) !== null && _f !== void 0 ? _f : undefined;
- const createdAt = (_g = object.createdAt) !== null && _g !== void 0 ? _g : undefined;
- const lastLoginAt = (_h = object.lastLoginAt) !== null && _h !== void 0 ? _h : undefined;
- const { uid, emailVerified, isAnonymous, providerData, stsTokenManager: plainObjectTokenManager } = object;
- _assert$4(uid && plainObjectTokenManager, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const stsTokenManager = StsTokenManager.fromJSON(this.name, plainObjectTokenManager);
- _assert$4(typeof uid === 'string', auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- assertStringOrUndefined(displayName, auth.name);
- assertStringOrUndefined(email, auth.name);
- _assert$4(typeof emailVerified === 'boolean', auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- _assert$4(typeof isAnonymous === 'boolean', auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- assertStringOrUndefined(phoneNumber, auth.name);
- assertStringOrUndefined(photoURL, auth.name);
- assertStringOrUndefined(tenantId, auth.name);
- assertStringOrUndefined(_redirectEventId, auth.name);
- assertStringOrUndefined(createdAt, auth.name);
- assertStringOrUndefined(lastLoginAt, auth.name);
- const user = new UserImpl({
- uid,
- auth,
- email,
- emailVerified,
- displayName,
- isAnonymous,
- photoURL,
- phoneNumber,
- tenantId,
- stsTokenManager,
- createdAt,
- lastLoginAt
- });
- if (providerData && Array.isArray(providerData)) {
- user.providerData = providerData.map(userInfo => (Object.assign({}, userInfo)));
- }
- if (_redirectEventId) {
- user._redirectEventId = _redirectEventId;
- }
- return user;
- }
- /**
- * Initialize a User from an idToken server response
- * @param auth
- * @param idTokenResponse
- */
- static async _fromIdTokenResponse(auth, idTokenResponse, isAnonymous = false) {
- const stsTokenManager = new StsTokenManager();
- stsTokenManager.updateFromServerResponse(idTokenResponse);
- // Initialize the Firebase Auth user.
- const user = new UserImpl({
- uid: idTokenResponse.localId,
- auth,
- stsTokenManager,
- isAnonymous
- });
- // Updates the user info and data and resolves with a user instance.
- await _reloadWithoutSaving(user);
- return user;
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const instanceCache = new Map();
- function _getInstance(cls) {
- debugAssert(cls instanceof Function, 'Expected a class definition');
- let instance = instanceCache.get(cls);
- if (instance) {
- debugAssert(instance instanceof cls, 'Instance stored in cache mismatched with class');
- return instance;
- }
- instance = new cls();
- instanceCache.set(cls, instance);
- return instance;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class InMemoryPersistence {
- constructor() {
- this.type = "NONE" /* PersistenceType.NONE */;
- this.storage = {};
- }
- async _isAvailable() {
- return true;
- }
- async _set(key, value) {
- this.storage[key] = value;
- }
- async _get(key) {
- const value = this.storage[key];
- return value === undefined ? null : value;
- }
- async _remove(key) {
- delete this.storage[key];
- }
- _addListener(_key, _listener) {
- // Listeners are not supported for in-memory storage since it cannot be shared across windows/workers
- return;
- }
- _removeListener(_key, _listener) {
- // Listeners are not supported for in-memory storage since it cannot be shared across windows/workers
- return;
- }
- }
- InMemoryPersistence.type = 'NONE';
- /**
- * An implementation of {@link Persistence} of type 'NONE'.
- *
- * @public
- */
- const inMemoryPersistence = InMemoryPersistence;
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _persistenceKeyName(key, apiKey, appName) {
- return `${"firebase" /* Namespace.PERSISTENCE */}:${key}:${apiKey}:${appName}`;
- }
- class PersistenceUserManager {
- constructor(persistence, auth, userKey) {
- this.persistence = persistence;
- this.auth = auth;
- this.userKey = userKey;
- const { config, name } = this.auth;
- this.fullUserKey = _persistenceKeyName(this.userKey, config.apiKey, name);
- this.fullPersistenceKey = _persistenceKeyName("persistence" /* KeyName.PERSISTENCE_USER */, config.apiKey, name);
- this.boundEventHandler = auth._onStorageEvent.bind(auth);
- this.persistence._addListener(this.fullUserKey, this.boundEventHandler);
- }
- setCurrentUser(user) {
- return this.persistence._set(this.fullUserKey, user.toJSON());
- }
- async getCurrentUser() {
- const blob = await this.persistence._get(this.fullUserKey);
- return blob ? UserImpl._fromJSON(this.auth, blob) : null;
- }
- removeCurrentUser() {
- return this.persistence._remove(this.fullUserKey);
- }
- savePersistenceForRedirect() {
- return this.persistence._set(this.fullPersistenceKey, this.persistence.type);
- }
- async setPersistence(newPersistence) {
- if (this.persistence === newPersistence) {
- return;
- }
- const currentUser = await this.getCurrentUser();
- await this.removeCurrentUser();
- this.persistence = newPersistence;
- if (currentUser) {
- return this.setCurrentUser(currentUser);
- }
- }
- delete() {
- this.persistence._removeListener(this.fullUserKey, this.boundEventHandler);
- }
- static async create(auth, persistenceHierarchy, userKey = "authUser" /* KeyName.AUTH_USER */) {
- if (!persistenceHierarchy.length) {
- return new PersistenceUserManager(_getInstance(inMemoryPersistence), auth, userKey);
- }
- // Eliminate any persistences that are not available
- const availablePersistences = (await Promise.all(persistenceHierarchy.map(async (persistence) => {
- if (await persistence._isAvailable()) {
- return persistence;
- }
- return undefined;
- }))).filter(persistence => persistence);
- // Fall back to the first persistence listed, or in memory if none available
- let selectedPersistence = availablePersistences[0] ||
- _getInstance(inMemoryPersistence);
- const key = _persistenceKeyName(userKey, auth.config.apiKey, auth.name);
- // Pull out the existing user, setting the chosen persistence to that
- // persistence if the user exists.
- let userToMigrate = null;
- // Note, here we check for a user in _all_ persistences, not just the
- // ones deemed available. If we can migrate a user out of a broken
- // persistence, we will (but only if that persistence supports migration).
- for (const persistence of persistenceHierarchy) {
- try {
- const blob = await persistence._get(key);
- if (blob) {
- const user = UserImpl._fromJSON(auth, blob); // throws for unparsable blob (wrong format)
- if (persistence !== selectedPersistence) {
- userToMigrate = user;
- }
- selectedPersistence = persistence;
- break;
- }
- }
- catch (_a) { }
- }
- // If we find the user in a persistence that does support migration, use
- // that migration path (of only persistences that support migration)
- const migrationHierarchy = availablePersistences.filter(p => p._shouldAllowMigration);
- // If the persistence does _not_ allow migration, just finish off here
- if (!selectedPersistence._shouldAllowMigration ||
- !migrationHierarchy.length) {
- return new PersistenceUserManager(selectedPersistence, auth, userKey);
- }
- selectedPersistence = migrationHierarchy[0];
- if (userToMigrate) {
- // This normally shouldn't throw since chosenPersistence.isAvailable() is true, but if it does
- // we'll just let it bubble to surface the error.
- await selectedPersistence._set(key, userToMigrate.toJSON());
- }
- // Attempt to clear the key in other persistences but ignore errors. This helps prevent issues
- // such as users getting stuck with a previous account after signing out and refreshing the tab.
- await Promise.all(persistenceHierarchy.map(async (persistence) => {
- if (persistence !== selectedPersistence) {
- try {
- await persistence._remove(key);
- }
- catch (_a) { }
- }
- }));
- return new PersistenceUserManager(selectedPersistence, auth, userKey);
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Determine the browser for the purposes of reporting usage to the API
- */
- function _getBrowserName(userAgent) {
- const ua = userAgent.toLowerCase();
- if (ua.includes('opera/') || ua.includes('opr/') || ua.includes('opios/')) {
- return "Opera" /* BrowserName.OPERA */;
- }
- else if (_isIEMobile(ua)) {
- // Windows phone IEMobile browser.
- return "IEMobile" /* BrowserName.IEMOBILE */;
- }
- else if (ua.includes('msie') || ua.includes('trident/')) {
- return "IE" /* BrowserName.IE */;
- }
- else if (ua.includes('edge/')) {
- return "Edge" /* BrowserName.EDGE */;
- }
- else if (_isFirefox(ua)) {
- return "Firefox" /* BrowserName.FIREFOX */;
- }
- else if (ua.includes('silk/')) {
- return "Silk" /* BrowserName.SILK */;
- }
- else if (_isBlackBerry(ua)) {
- // Blackberry browser.
- return "Blackberry" /* BrowserName.BLACKBERRY */;
- }
- else if (_isWebOS(ua)) {
- // WebOS default browser.
- return "Webos" /* BrowserName.WEBOS */;
- }
- else if (_isSafari(ua)) {
- return "Safari" /* BrowserName.SAFARI */;
- }
- else if ((ua.includes('chrome/') || _isChromeIOS(ua)) &&
- !ua.includes('edge/')) {
- return "Chrome" /* BrowserName.CHROME */;
- }
- else if (_isAndroid(ua)) {
- // Android stock browser.
- return "Android" /* BrowserName.ANDROID */;
- }
- else {
- // Most modern browsers have name/version at end of user agent string.
- const re = /([a-zA-Z\d\.]+)\/[a-zA-Z\d\.]*$/;
- const matches = userAgent.match(re);
- if ((matches === null || matches === void 0 ? void 0 : matches.length) === 2) {
- return matches[1];
- }
- }
- return "Other" /* BrowserName.OTHER */;
- }
- function _isFirefox(ua = getUA()) {
- return /firefox\//i.test(ua);
- }
- function _isSafari(userAgent = getUA()) {
- const ua = userAgent.toLowerCase();
- return (ua.includes('safari/') &&
- !ua.includes('chrome/') &&
- !ua.includes('crios/') &&
- !ua.includes('android'));
- }
- function _isChromeIOS(ua = getUA()) {
- return /crios\//i.test(ua);
- }
- function _isIEMobile(ua = getUA()) {
- return /iemobile/i.test(ua);
- }
- function _isAndroid(ua = getUA()) {
- return /android/i.test(ua);
- }
- function _isBlackBerry(ua = getUA()) {
- return /blackberry/i.test(ua);
- }
- function _isWebOS(ua = getUA()) {
- return /webos/i.test(ua);
- }
- function _isIOS(ua = getUA()) {
- return (/iphone|ipad|ipod/i.test(ua) ||
- (/macintosh/i.test(ua) && /mobile/i.test(ua)));
- }
- function _isIOS7Or8(ua = getUA()) {
- return (/(iPad|iPhone|iPod).*OS 7_\d/i.test(ua) ||
- /(iPad|iPhone|iPod).*OS 8_\d/i.test(ua));
- }
- function _isIOSStandalone(ua = getUA()) {
- var _a;
- return _isIOS(ua) && !!((_a = window.navigator) === null || _a === void 0 ? void 0 : _a.standalone);
- }
- function _isIE10() {
- return isIE() && document.documentMode === 10;
- }
- function _isMobileBrowser(ua = getUA()) {
- // TODO: implement getBrowserName equivalent for OS.
- return (_isIOS(ua) ||
- _isAndroid(ua) ||
- _isWebOS(ua) ||
- _isBlackBerry(ua) ||
- /windows phone/i.test(ua) ||
- _isIEMobile(ua));
- }
- function _isIframe() {
- try {
- // Check that the current window is not the top window.
- // If so, return true.
- return !!(window && window !== window.top);
- }
- catch (e) {
- return false;
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /*
- * Determine the SDK version string
- */
- function _getClientVersion(clientPlatform, frameworks = []) {
- let reportedPlatform;
- switch (clientPlatform) {
- case "Browser" /* ClientPlatform.BROWSER */:
- // In a browser environment, report the browser name.
- reportedPlatform = _getBrowserName(getUA());
- break;
- case "Worker" /* ClientPlatform.WORKER */:
- // Technically a worker runs from a browser but we need to differentiate a
- // worker from a browser.
- // For example: Chrome-Worker/JsCore/4.9.1/FirebaseCore-web.
- reportedPlatform = `${_getBrowserName(getUA())}-${clientPlatform}`;
- break;
- default:
- reportedPlatform = clientPlatform;
- }
- const reportedFrameworks = frameworks.length
- ? frameworks.join(',')
- : 'FirebaseCore-web'; /* default value if no other framework is used */
- return `${reportedPlatform}/${"JsCore" /* ClientImplementation.CORE */}/${SDK_VERSION$1}/${reportedFrameworks}`;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function getRecaptchaParams(auth) {
- return ((await _performApiRequest(auth, "GET" /* HttpMethod.GET */, "/v1/recaptchaParams" /* Endpoint.GET_RECAPTCHA_PARAM */)).recaptchaSiteKey || '');
- }
- async function getRecaptchaConfig(auth, request) {
- return _performApiRequest(auth, "GET" /* HttpMethod.GET */, "/v2/recaptchaConfig" /* Endpoint.GET_RECAPTCHA_CONFIG */, _addTidIfNecessary(auth, request));
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function isV2(grecaptcha) {
- return (grecaptcha !== undefined &&
- grecaptcha.getResponse !== undefined);
- }
- function isEnterprise(grecaptcha) {
- return (grecaptcha !== undefined &&
- grecaptcha.enterprise !== undefined);
- }
- class RecaptchaConfig {
- constructor(response) {
- /**
- * The reCAPTCHA site key.
- */
- this.siteKey = '';
- /**
- * The reCAPTCHA enablement status of the {@link EmailAuthProvider} for the current tenant.
- */
- this.emailPasswordEnabled = false;
- if (response.recaptchaKey === undefined) {
- throw new Error('recaptchaKey undefined');
- }
- // Example response.recaptchaKey: "projects/proj123/keys/sitekey123"
- this.siteKey = response.recaptchaKey.split('/')[3];
- this.emailPasswordEnabled = response.recaptchaEnforcementState.some(enforcementState => enforcementState.provider === 'EMAIL_PASSWORD_PROVIDER' &&
- enforcementState.enforcementState !== 'OFF');
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function getScriptParentElement() {
- var _a, _b;
- return (_b = (_a = document.getElementsByTagName('head')) === null || _a === void 0 ? void 0 : _a[0]) !== null && _b !== void 0 ? _b : document;
- }
- function _loadJS(url) {
- // TODO: consider adding timeout support & cancellation
- return new Promise((resolve, reject) => {
- const el = document.createElement('script');
- el.setAttribute('src', url);
- el.onload = resolve;
- el.onerror = e => {
- const error = _createError("internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- error.customData = e;
- reject(error);
- };
- el.type = 'text/javascript';
- el.charset = 'UTF-8';
- getScriptParentElement().appendChild(el);
- });
- }
- function _generateCallbackName(prefix) {
- return `__${prefix}${Math.floor(Math.random() * 1000000)}`;
- }
-
- /* eslint-disable @typescript-eslint/no-require-imports */
- const RECAPTCHA_ENTERPRISE_URL = 'https://www.google.com/recaptcha/enterprise.js?render=';
- const RECAPTCHA_ENTERPRISE_VERIFIER_TYPE = 'recaptcha-enterprise';
- const FAKE_TOKEN = 'NO_RECAPTCHA';
- class RecaptchaEnterpriseVerifier {
- /**
- *
- * @param authExtern - The corresponding Firebase {@link Auth} instance.
- *
- */
- constructor(authExtern) {
- /**
- * Identifies the type of application verifier (e.g. "recaptcha-enterprise").
- */
- this.type = RECAPTCHA_ENTERPRISE_VERIFIER_TYPE;
- this.auth = _castAuth(authExtern);
- }
- /**
- * Executes the verification process.
- *
- * @returns A Promise for a token that can be used to assert the validity of a request.
- */
- async verify(action = 'verify', forceRefresh = false) {
- async function retrieveSiteKey(auth) {
- if (!forceRefresh) {
- if (auth.tenantId == null && auth._agentRecaptchaConfig != null) {
- return auth._agentRecaptchaConfig.siteKey;
- }
- if (auth.tenantId != null &&
- auth._tenantRecaptchaConfigs[auth.tenantId] !== undefined) {
- return auth._tenantRecaptchaConfigs[auth.tenantId].siteKey;
- }
- }
- return new Promise(async (resolve, reject) => {
- getRecaptchaConfig(auth, {
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */,
- version: "RECAPTCHA_ENTERPRISE" /* RecaptchaVersion.ENTERPRISE */
- })
- .then(response => {
- if (response.recaptchaKey === undefined) {
- reject(new Error('recaptcha Enterprise site key undefined'));
- }
- else {
- const config = new RecaptchaConfig(response);
- if (auth.tenantId == null) {
- auth._agentRecaptchaConfig = config;
- }
- else {
- auth._tenantRecaptchaConfigs[auth.tenantId] = config;
- }
- return resolve(config.siteKey);
- }
- })
- .catch(error => {
- reject(error);
- });
- });
- }
- function retrieveRecaptchaToken(siteKey, resolve, reject) {
- const grecaptcha = window.grecaptcha;
- if (isEnterprise(grecaptcha)) {
- grecaptcha.enterprise.ready(() => {
- grecaptcha.enterprise
- .execute(siteKey, { action })
- .then(token => {
- resolve(token);
- })
- .catch(() => {
- resolve(FAKE_TOKEN);
- });
- });
- }
- else {
- reject(Error('No reCAPTCHA enterprise script loaded.'));
- }
- }
- return new Promise((resolve, reject) => {
- retrieveSiteKey(this.auth)
- .then(siteKey => {
- if (!forceRefresh && isEnterprise(window.grecaptcha)) {
- retrieveRecaptchaToken(siteKey, resolve, reject);
- }
- else {
- if (typeof window === 'undefined') {
- reject(new Error('RecaptchaVerifier is only supported in browser'));
- return;
- }
- _loadJS(RECAPTCHA_ENTERPRISE_URL + siteKey)
- .then(() => {
- retrieveRecaptchaToken(siteKey, resolve, reject);
- })
- .catch(error => {
- reject(error);
- });
- }
- })
- .catch(error => {
- reject(error);
- });
- });
- }
- }
- async function injectRecaptchaFields(auth, request, action, captchaResp = false) {
- const verifier = new RecaptchaEnterpriseVerifier(auth);
- let captchaResponse;
- try {
- captchaResponse = await verifier.verify(action);
- }
- catch (error) {
- captchaResponse = await verifier.verify(action, true);
- }
- const newRequest = Object.assign({}, request);
- if (!captchaResp) {
- Object.assign(newRequest, { captchaResponse });
- }
- else {
- Object.assign(newRequest, { 'captchaResp': captchaResponse });
- }
- Object.assign(newRequest, { 'clientType': "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */ });
- Object.assign(newRequest, {
- 'recaptchaVersion': "RECAPTCHA_ENTERPRISE" /* RecaptchaVersion.ENTERPRISE */
- });
- return newRequest;
- }
-
- /**
- * @license
- * Copyright 2022 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class AuthMiddlewareQueue {
- constructor(auth) {
- this.auth = auth;
- this.queue = [];
- }
- pushCallback(callback, onAbort) {
- // The callback could be sync or async. Wrap it into a
- // function that is always async.
- const wrappedCallback = (user) => new Promise((resolve, reject) => {
- try {
- const result = callback(user);
- // Either resolve with existing promise or wrap a non-promise
- // return value into a promise.
- resolve(result);
- }
- catch (e) {
- // Sync callback throws.
- reject(e);
- }
- });
- // Attach the onAbort if present
- wrappedCallback.onAbort = onAbort;
- this.queue.push(wrappedCallback);
- const index = this.queue.length - 1;
- return () => {
- // Unsubscribe. Replace with no-op. Do not remove from array, or it will disturb
- // indexing of other elements.
- this.queue[index] = () => Promise.resolve();
- };
- }
- async runMiddleware(nextUser) {
- if (this.auth.currentUser === nextUser) {
- return;
- }
- // While running the middleware, build a temporary stack of onAbort
- // callbacks to call if one middleware callback rejects.
- const onAbortStack = [];
- try {
- for (const beforeStateCallback of this.queue) {
- await beforeStateCallback(nextUser);
- // Only push the onAbort if the callback succeeds
- if (beforeStateCallback.onAbort) {
- onAbortStack.push(beforeStateCallback.onAbort);
- }
- }
- }
- catch (e) {
- // Run all onAbort, with separate try/catch to ignore any errors and
- // continue
- onAbortStack.reverse();
- for (const onAbort of onAbortStack) {
- try {
- onAbort();
- }
- catch (_) {
- /* swallow error */
- }
- }
- throw this.auth._errorFactory.create("login-blocked" /* AuthErrorCode.LOGIN_BLOCKED */, {
- originalMessage: e === null || e === void 0 ? void 0 : e.message
- });
- }
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class AuthImpl {
- constructor(app, heartbeatServiceProvider, appCheckServiceProvider, config) {
- this.app = app;
- this.heartbeatServiceProvider = heartbeatServiceProvider;
- this.appCheckServiceProvider = appCheckServiceProvider;
- this.config = config;
- this.currentUser = null;
- this.emulatorConfig = null;
- this.operations = Promise.resolve();
- this.authStateSubscription = new Subscription(this);
- this.idTokenSubscription = new Subscription(this);
- this.beforeStateQueue = new AuthMiddlewareQueue(this);
- this.redirectUser = null;
- this.isProactiveRefreshEnabled = false;
- // Any network calls will set this to true and prevent subsequent emulator
- // initialization
- this._canInitEmulator = true;
- this._isInitialized = false;
- this._deleted = false;
- this._initializationPromise = null;
- this._popupRedirectResolver = null;
- this._errorFactory = _DEFAULT_AUTH_ERROR_FACTORY;
- this._agentRecaptchaConfig = null;
- this._tenantRecaptchaConfigs = {};
- // Tracks the last notified UID for state change listeners to prevent
- // repeated calls to the callbacks. Undefined means it's never been
- // called, whereas null means it's been called with a signed out user
- this.lastNotifiedUid = undefined;
- this.languageCode = null;
- this.tenantId = null;
- this.settings = { appVerificationDisabledForTesting: false };
- this.frameworks = [];
- this.name = app.name;
- this.clientVersion = config.sdkClientVersion;
- }
- _initializeWithPersistence(persistenceHierarchy, popupRedirectResolver) {
- if (popupRedirectResolver) {
- this._popupRedirectResolver = _getInstance(popupRedirectResolver);
- }
- // Have to check for app deletion throughout initialization (after each
- // promise resolution)
- this._initializationPromise = this.queue(async () => {
- var _a, _b;
- if (this._deleted) {
- return;
- }
- this.persistenceManager = await PersistenceUserManager.create(this, persistenceHierarchy);
- if (this._deleted) {
- return;
- }
- // Initialize the resolver early if necessary (only applicable to web:
- // this will cause the iframe to load immediately in certain cases)
- if ((_a = this._popupRedirectResolver) === null || _a === void 0 ? void 0 : _a._shouldInitProactively) {
- // If this fails, don't halt auth loading
- try {
- await this._popupRedirectResolver._initialize(this);
- }
- catch (e) {
- /* Ignore the error */
- }
- }
- await this.initializeCurrentUser(popupRedirectResolver);
- this.lastNotifiedUid = ((_b = this.currentUser) === null || _b === void 0 ? void 0 : _b.uid) || null;
- if (this._deleted) {
- return;
- }
- this._isInitialized = true;
- });
- return this._initializationPromise;
- }
- /**
- * If the persistence is changed in another window, the user manager will let us know
- */
- async _onStorageEvent() {
- if (this._deleted) {
- return;
- }
- const user = await this.assertedPersistence.getCurrentUser();
- if (!this.currentUser && !user) {
- // No change, do nothing (was signed out and remained signed out).
- return;
- }
- // If the same user is to be synchronized.
- if (this.currentUser && user && this.currentUser.uid === user.uid) {
- // Data update, simply copy data changes.
- this._currentUser._assign(user);
- // If tokens changed from previous user tokens, this will trigger
- // notifyAuthListeners_.
- await this.currentUser.getIdToken();
- return;
- }
- // Update current Auth state. Either a new login or logout.
- // Skip blocking callbacks, they should not apply to a change in another tab.
- await this._updateCurrentUser(user, /* skipBeforeStateCallbacks */ true);
- }
- async initializeCurrentUser(popupRedirectResolver) {
- var _a;
- // First check to see if we have a pending redirect event.
- const previouslyStoredUser = (await this.assertedPersistence.getCurrentUser());
- let futureCurrentUser = previouslyStoredUser;
- let needsTocheckMiddleware = false;
- if (popupRedirectResolver && this.config.authDomain) {
- await this.getOrInitRedirectPersistenceManager();
- const redirectUserEventId = (_a = this.redirectUser) === null || _a === void 0 ? void 0 : _a._redirectEventId;
- const storedUserEventId = futureCurrentUser === null || futureCurrentUser === void 0 ? void 0 : futureCurrentUser._redirectEventId;
- const result = await this.tryRedirectSignIn(popupRedirectResolver);
- // If the stored user (i.e. the old "currentUser") has a redirectId that
- // matches the redirect user, then we want to initially sign in with the
- // new user object from result.
- // TODO(samgho): More thoroughly test all of this
- if ((!redirectUserEventId || redirectUserEventId === storedUserEventId) &&
- (result === null || result === void 0 ? void 0 : result.user)) {
- futureCurrentUser = result.user;
- needsTocheckMiddleware = true;
- }
- }
- // If no user in persistence, there is no current user. Set to null.
- if (!futureCurrentUser) {
- return this.directlySetCurrentUser(null);
- }
- if (!futureCurrentUser._redirectEventId) {
- // This isn't a redirect link operation, we can reload and bail.
- // First though, ensure that we check the middleware is happy.
- if (needsTocheckMiddleware) {
- try {
- await this.beforeStateQueue.runMiddleware(futureCurrentUser);
- }
- catch (e) {
- futureCurrentUser = previouslyStoredUser;
- // We know this is available since the bit is only set when the
- // resolver is available
- this._popupRedirectResolver._overrideRedirectResult(this, () => Promise.reject(e));
- }
- }
- if (futureCurrentUser) {
- return this.reloadAndSetCurrentUserOrClear(futureCurrentUser);
- }
- else {
- return this.directlySetCurrentUser(null);
- }
- }
- _assert$4(this._popupRedirectResolver, this, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- await this.getOrInitRedirectPersistenceManager();
- // If the redirect user's event ID matches the current user's event ID,
- // DO NOT reload the current user, otherwise they'll be cleared from storage.
- // This is important for the reauthenticateWithRedirect() flow.
- if (this.redirectUser &&
- this.redirectUser._redirectEventId === futureCurrentUser._redirectEventId) {
- return this.directlySetCurrentUser(futureCurrentUser);
- }
- return this.reloadAndSetCurrentUserOrClear(futureCurrentUser);
- }
- async tryRedirectSignIn(redirectResolver) {
- // The redirect user needs to be checked (and signed in if available)
- // during auth initialization. All of the normal sign in and link/reauth
- // flows call back into auth and push things onto the promise queue. We
- // need to await the result of the redirect sign in *inside the promise
- // queue*. This presents a problem: we run into deadlock. See:
- // ┌> [Initialization] ─────┐
- // ┌> [] │
- // └─ [getRedirectResult] <─┘
- // where [] are tasks on the queue and arrows denote awaits
- // Initialization will never complete because it's waiting on something
- // that's waiting for initialization to complete!
- //
- // Instead, this method calls getRedirectResult() (stored in
- // _completeRedirectFn) with an optional parameter that instructs all of
- // the underlying auth operations to skip anything that mutates auth state.
- let result = null;
- try {
- // We know this._popupRedirectResolver is set since redirectResolver
- // is passed in. The _completeRedirectFn expects the unwrapped extern.
- result = await this._popupRedirectResolver._completeRedirectFn(this, redirectResolver, true);
- }
- catch (e) {
- // Swallow any errors here; the code can retrieve them in
- // getRedirectResult().
- await this._setRedirectUser(null);
- }
- return result;
- }
- async reloadAndSetCurrentUserOrClear(user) {
- try {
- await _reloadWithoutSaving(user);
- }
- catch (e) {
- if ((e === null || e === void 0 ? void 0 : e.code) !==
- `auth/${"network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */}`) {
- // Something's wrong with the user's token. Log them out and remove
- // them from storage
- return this.directlySetCurrentUser(null);
- }
- }
- return this.directlySetCurrentUser(user);
- }
- useDeviceLanguage() {
- this.languageCode = _getUserLanguage();
- }
- async _delete() {
- this._deleted = true;
- }
- async updateCurrentUser(userExtern) {
- // The public updateCurrentUser method needs to make a copy of the user,
- // and also check that the project matches
- const user = userExtern
- ? getModularInstance(userExtern)
- : null;
- if (user) {
- _assert$4(user.auth.config.apiKey === this.config.apiKey, this, "invalid-user-token" /* AuthErrorCode.INVALID_AUTH */);
- }
- return this._updateCurrentUser(user && user._clone(this));
- }
- async _updateCurrentUser(user, skipBeforeStateCallbacks = false) {
- if (this._deleted) {
- return;
- }
- if (user) {
- _assert$4(this.tenantId === user.tenantId, this, "tenant-id-mismatch" /* AuthErrorCode.TENANT_ID_MISMATCH */);
- }
- if (!skipBeforeStateCallbacks) {
- await this.beforeStateQueue.runMiddleware(user);
- }
- return this.queue(async () => {
- await this.directlySetCurrentUser(user);
- this.notifyAuthListeners();
- });
- }
- async signOut() {
- // Run first, to block _setRedirectUser() if any callbacks fail.
- await this.beforeStateQueue.runMiddleware(null);
- // Clear the redirect user when signOut is called
- if (this.redirectPersistenceManager || this._popupRedirectResolver) {
- await this._setRedirectUser(null);
- }
- // Prevent callbacks from being called again in _updateCurrentUser, as
- // they were already called in the first line.
- return this._updateCurrentUser(null, /* skipBeforeStateCallbacks */ true);
- }
- setPersistence(persistence) {
- return this.queue(async () => {
- await this.assertedPersistence.setPersistence(_getInstance(persistence));
- });
- }
- async initializeRecaptchaConfig() {
- const response = await getRecaptchaConfig(this, {
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */,
- version: "RECAPTCHA_ENTERPRISE" /* RecaptchaVersion.ENTERPRISE */
- });
- const config = new RecaptchaConfig(response);
- if (this.tenantId == null) {
- this._agentRecaptchaConfig = config;
- }
- else {
- this._tenantRecaptchaConfigs[this.tenantId] = config;
- }
- if (config.emailPasswordEnabled) {
- const verifier = new RecaptchaEnterpriseVerifier(this);
- void verifier.verify();
- }
- }
- _getRecaptchaConfig() {
- if (this.tenantId == null) {
- return this._agentRecaptchaConfig;
- }
- else {
- return this._tenantRecaptchaConfigs[this.tenantId];
- }
- }
- _getPersistence() {
- return this.assertedPersistence.persistence.type;
- }
- _updateErrorMap(errorMap) {
- this._errorFactory = new ErrorFactory('auth', 'Firebase', errorMap());
- }
- onAuthStateChanged(nextOrObserver, error, completed) {
- return this.registerStateListener(this.authStateSubscription, nextOrObserver, error, completed);
- }
- beforeAuthStateChanged(callback, onAbort) {
- return this.beforeStateQueue.pushCallback(callback, onAbort);
- }
- onIdTokenChanged(nextOrObserver, error, completed) {
- return this.registerStateListener(this.idTokenSubscription, nextOrObserver, error, completed);
- }
- toJSON() {
- var _a;
- return {
- apiKey: this.config.apiKey,
- authDomain: this.config.authDomain,
- appName: this.name,
- currentUser: (_a = this._currentUser) === null || _a === void 0 ? void 0 : _a.toJSON()
- };
- }
- async _setRedirectUser(user, popupRedirectResolver) {
- const redirectManager = await this.getOrInitRedirectPersistenceManager(popupRedirectResolver);
- return user === null
- ? redirectManager.removeCurrentUser()
- : redirectManager.setCurrentUser(user);
- }
- async getOrInitRedirectPersistenceManager(popupRedirectResolver) {
- if (!this.redirectPersistenceManager) {
- const resolver = (popupRedirectResolver && _getInstance(popupRedirectResolver)) ||
- this._popupRedirectResolver;
- _assert$4(resolver, this, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- this.redirectPersistenceManager = await PersistenceUserManager.create(this, [_getInstance(resolver._redirectPersistence)], "redirectUser" /* KeyName.REDIRECT_USER */);
- this.redirectUser =
- await this.redirectPersistenceManager.getCurrentUser();
- }
- return this.redirectPersistenceManager;
- }
- async _redirectUserForId(id) {
- var _a, _b;
- // Make sure we've cleared any pending persistence actions if we're not in
- // the initializer
- if (this._isInitialized) {
- await this.queue(async () => { });
- }
- if (((_a = this._currentUser) === null || _a === void 0 ? void 0 : _a._redirectEventId) === id) {
- return this._currentUser;
- }
- if (((_b = this.redirectUser) === null || _b === void 0 ? void 0 : _b._redirectEventId) === id) {
- return this.redirectUser;
- }
- return null;
- }
- async _persistUserIfCurrent(user) {
- if (user === this.currentUser) {
- return this.queue(async () => this.directlySetCurrentUser(user));
- }
- }
- /** Notifies listeners only if the user is current */
- _notifyListenersIfCurrent(user) {
- if (user === this.currentUser) {
- this.notifyAuthListeners();
- }
- }
- _key() {
- return `${this.config.authDomain}:${this.config.apiKey}:${this.name}`;
- }
- _startProactiveRefresh() {
- this.isProactiveRefreshEnabled = true;
- if (this.currentUser) {
- this._currentUser._startProactiveRefresh();
- }
- }
- _stopProactiveRefresh() {
- this.isProactiveRefreshEnabled = false;
- if (this.currentUser) {
- this._currentUser._stopProactiveRefresh();
- }
- }
- /** Returns the current user cast as the internal type */
- get _currentUser() {
- return this.currentUser;
- }
- notifyAuthListeners() {
- var _a, _b;
- if (!this._isInitialized) {
- return;
- }
- this.idTokenSubscription.next(this.currentUser);
- const currentUid = (_b = (_a = this.currentUser) === null || _a === void 0 ? void 0 : _a.uid) !== null && _b !== void 0 ? _b : null;
- if (this.lastNotifiedUid !== currentUid) {
- this.lastNotifiedUid = currentUid;
- this.authStateSubscription.next(this.currentUser);
- }
- }
- registerStateListener(subscription, nextOrObserver, error, completed) {
- if (this._deleted) {
- return () => { };
- }
- const cb = typeof nextOrObserver === 'function'
- ? nextOrObserver
- : nextOrObserver.next.bind(nextOrObserver);
- const promise = this._isInitialized
- ? Promise.resolve()
- : this._initializationPromise;
- _assert$4(promise, this, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- // The callback needs to be called asynchronously per the spec.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- promise.then(() => cb(this.currentUser));
- if (typeof nextOrObserver === 'function') {
- return subscription.addObserver(nextOrObserver, error, completed);
- }
- else {
- return subscription.addObserver(nextOrObserver);
- }
- }
- /**
- * Unprotected (from race conditions) method to set the current user. This
- * should only be called from within a queued callback. This is necessary
- * because the queue shouldn't rely on another queued callback.
- */
- async directlySetCurrentUser(user) {
- if (this.currentUser && this.currentUser !== user) {
- this._currentUser._stopProactiveRefresh();
- }
- if (user && this.isProactiveRefreshEnabled) {
- user._startProactiveRefresh();
- }
- this.currentUser = user;
- if (user) {
- await this.assertedPersistence.setCurrentUser(user);
- }
- else {
- await this.assertedPersistence.removeCurrentUser();
- }
- }
- queue(action) {
- // In case something errors, the callback still should be called in order
- // to keep the promise chain alive
- this.operations = this.operations.then(action, action);
- return this.operations;
- }
- get assertedPersistence() {
- _assert$4(this.persistenceManager, this, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return this.persistenceManager;
- }
- _logFramework(framework) {
- if (!framework || this.frameworks.includes(framework)) {
- return;
- }
- this.frameworks.push(framework);
- // Sort alphabetically so that "FirebaseCore-web,FirebaseUI-web" and
- // "FirebaseUI-web,FirebaseCore-web" aren't viewed as different.
- this.frameworks.sort();
- this.clientVersion = _getClientVersion(this.config.clientPlatform, this._getFrameworks());
- }
- _getFrameworks() {
- return this.frameworks;
- }
- async _getAdditionalHeaders() {
- var _a;
- // Additional headers on every request
- const headers = {
- ["X-Client-Version" /* HttpHeader.X_CLIENT_VERSION */]: this.clientVersion
- };
- if (this.app.options.appId) {
- headers["X-Firebase-gmpid" /* HttpHeader.X_FIREBASE_GMPID */] = this.app.options.appId;
- }
- // If the heartbeat service exists, add the heartbeat string
- const heartbeatsHeader = await ((_a = this.heartbeatServiceProvider
- .getImmediate({
- optional: true
- })) === null || _a === void 0 ? void 0 : _a.getHeartbeatsHeader());
- if (heartbeatsHeader) {
- headers["X-Firebase-Client" /* HttpHeader.X_FIREBASE_CLIENT */] = heartbeatsHeader;
- }
- // If the App Check service exists, add the App Check token in the headers
- const appCheckToken = await this._getAppCheckToken();
- if (appCheckToken) {
- headers["X-Firebase-AppCheck" /* HttpHeader.X_FIREBASE_APP_CHECK */] = appCheckToken;
- }
- return headers;
- }
- async _getAppCheckToken() {
- var _a;
- const appCheckTokenResult = await ((_a = this.appCheckServiceProvider
- .getImmediate({ optional: true })) === null || _a === void 0 ? void 0 : _a.getToken());
- if (appCheckTokenResult === null || appCheckTokenResult === void 0 ? void 0 : appCheckTokenResult.error) {
- // Context: appCheck.getToken() will never throw even if an error happened.
- // In the error case, a dummy token will be returned along with an error field describing
- // the error. In general, we shouldn't care about the error condition and just use
- // the token (actual or dummy) to send requests.
- _logWarn(`Error while retrieving App Check token: ${appCheckTokenResult.error}`);
- }
- return appCheckTokenResult === null || appCheckTokenResult === void 0 ? void 0 : appCheckTokenResult.token;
- }
- }
- /**
- * Method to be used to cast down to our private implmentation of Auth.
- * It will also handle unwrapping from the compat type if necessary
- *
- * @param auth Auth object passed in from developer
- */
- function _castAuth(auth) {
- return getModularInstance(auth);
- }
- /** Helper class to wrap subscriber logic */
- class Subscription {
- constructor(auth) {
- this.auth = auth;
- this.observer = null;
- this.addObserver = createSubscribe(observer => (this.observer = observer));
- }
- get next() {
- _assert$4(this.observer, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return this.observer.next.bind(this.observer);
- }
- }
- function _initializeAuthInstance(auth, deps) {
- const persistence = (deps === null || deps === void 0 ? void 0 : deps.persistence) || [];
- const hierarchy = (Array.isArray(persistence) ? persistence : [persistence]).map(_getInstance);
- if (deps === null || deps === void 0 ? void 0 : deps.errorMap) {
- auth._updateErrorMap(deps.errorMap);
- }
- // This promise is intended to float; auth initialization happens in the
- // background, meanwhile the auth object may be used by the app.
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- auth._initializeWithPersistence(hierarchy, deps === null || deps === void 0 ? void 0 : deps.popupRedirectResolver);
- }
-
- /**
- * Changes the {@link Auth} instance to communicate with the Firebase Auth Emulator, instead of production
- * Firebase Auth services.
- *
- * @remarks
- * This must be called synchronously immediately following the first call to
- * {@link initializeAuth}. Do not use with production credentials as emulator
- * traffic is not encrypted.
- *
- *
- * @example
- * ```javascript
- * connectAuthEmulator(auth, 'http://127.0.0.1:9099', { disableWarnings: true });
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param url - The URL at which the emulator is running (eg, 'http://localhost:9099').
- * @param options - Optional. `options.disableWarnings` defaults to `false`. Set it to
- * `true` to disable the warning banner attached to the DOM.
- *
- * @public
- */
- function connectAuthEmulator(auth, url, options) {
- const authInternal = _castAuth(auth);
- _assert$4(authInternal._canInitEmulator, authInternal, "emulator-config-failed" /* AuthErrorCode.EMULATOR_CONFIG_FAILED */);
- _assert$4(/^https?:\/\//.test(url), authInternal, "invalid-emulator-scheme" /* AuthErrorCode.INVALID_EMULATOR_SCHEME */);
- const disableWarnings = !!(options === null || options === void 0 ? void 0 : options.disableWarnings);
- const protocol = extractProtocol(url);
- const { host, port } = extractHostAndPort(url);
- const portStr = port === null ? '' : `:${port}`;
- // Always replace path with "/" (even if input url had no path at all, or had a different one).
- authInternal.config.emulator = { url: `${protocol}//${host}${portStr}/` };
- authInternal.settings.appVerificationDisabledForTesting = true;
- authInternal.emulatorConfig = Object.freeze({
- host,
- port,
- protocol: protocol.replace(':', ''),
- options: Object.freeze({ disableWarnings })
- });
- if (!disableWarnings) {
- emitEmulatorWarning();
- }
- }
- function extractProtocol(url) {
- const protocolEnd = url.indexOf(':');
- return protocolEnd < 0 ? '' : url.substr(0, protocolEnd + 1);
- }
- function extractHostAndPort(url) {
- const protocol = extractProtocol(url);
- const authority = /(\/\/)?([^?#/]+)/.exec(url.substr(protocol.length)); // Between // and /, ? or #.
- if (!authority) {
- return { host: '', port: null };
- }
- const hostAndPort = authority[2].split('@').pop() || ''; // Strip out "username:password@".
- const bracketedIPv6 = /^(\[[^\]]+\])(:|$)/.exec(hostAndPort);
- if (bracketedIPv6) {
- const host = bracketedIPv6[1];
- return { host, port: parsePort(hostAndPort.substr(host.length + 1)) };
- }
- else {
- const [host, port] = hostAndPort.split(':');
- return { host, port: parsePort(port) };
- }
- }
- function parsePort(portStr) {
- if (!portStr) {
- return null;
- }
- const port = Number(portStr);
- if (isNaN(port)) {
- return null;
- }
- return port;
- }
- function emitEmulatorWarning() {
- function attachBanner() {
- const el = document.createElement('p');
- const sty = el.style;
- el.innerText =
- 'Running in emulator mode. Do not use with production credentials.';
- sty.position = 'fixed';
- sty.width = '100%';
- sty.backgroundColor = '#ffffff';
- sty.border = '.1em solid #000000';
- sty.color = '#b50000';
- sty.bottom = '0px';
- sty.left = '0px';
- sty.margin = '0px';
- sty.zIndex = '10000';
- sty.textAlign = 'center';
- el.classList.add('firebase-emulator-warning');
- document.body.appendChild(el);
- }
- if (typeof console !== 'undefined' && typeof console.info === 'function') {
- console.info('WARNING: You are using the Auth Emulator,' +
- ' which is intended for local testing only. Do not use with' +
- ' production credentials.');
- }
- if (typeof window !== 'undefined' && typeof document !== 'undefined') {
- if (document.readyState === 'loading') {
- window.addEventListener('DOMContentLoaded', attachBanner);
- }
- else {
- attachBanner();
- }
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Interface that represents the credentials returned by an {@link AuthProvider}.
- *
- * @remarks
- * Implementations specify the details about each auth provider's credential requirements.
- *
- * @public
- */
- class AuthCredential {
- /** @internal */
- constructor(
- /**
- * The authentication provider ID for the credential.
- *
- * @remarks
- * For example, 'facebook.com', or 'google.com'.
- */
- providerId,
- /**
- * The authentication sign in method for the credential.
- *
- * @remarks
- * For example, {@link SignInMethod}.EMAIL_PASSWORD, or
- * {@link SignInMethod}.EMAIL_LINK. This corresponds to the sign-in method
- * identifier as returned in {@link fetchSignInMethodsForEmail}.
- */
- signInMethod) {
- this.providerId = providerId;
- this.signInMethod = signInMethod;
- }
- /**
- * Returns a JSON-serializable representation of this object.
- *
- * @returns a JSON-serializable representation of this object.
- */
- toJSON() {
- return debugFail('not implemented');
- }
- /** @internal */
- _getIdTokenResponse(_auth) {
- return debugFail('not implemented');
- }
- /** @internal */
- _linkToIdToken(_auth, _idToken) {
- return debugFail('not implemented');
- }
- /** @internal */
- _getReauthenticationResolver(_auth) {
- return debugFail('not implemented');
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function resetPassword(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:resetPassword" /* Endpoint.RESET_PASSWORD */, _addTidIfNecessary(auth, request));
- }
- async function updateEmailPassword(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:update" /* Endpoint.SET_ACCOUNT_INFO */, request);
- }
- async function applyActionCode$1(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:update" /* Endpoint.SET_ACCOUNT_INFO */, _addTidIfNecessary(auth, request));
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function signInWithPassword(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithPassword" /* Endpoint.SIGN_IN_WITH_PASSWORD */, _addTidIfNecessary(auth, request));
- }
- async function sendOobCode(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:sendOobCode" /* Endpoint.SEND_OOB_CODE */, _addTidIfNecessary(auth, request));
- }
- async function sendEmailVerification$1(auth, request) {
- return sendOobCode(auth, request);
- }
- async function sendPasswordResetEmail$1(auth, request) {
- return sendOobCode(auth, request);
- }
- async function sendSignInLinkToEmail$1(auth, request) {
- return sendOobCode(auth, request);
- }
- async function verifyAndChangeEmail(auth, request) {
- return sendOobCode(auth, request);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function signInWithEmailLink$1(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithEmailLink" /* Endpoint.SIGN_IN_WITH_EMAIL_LINK */, _addTidIfNecessary(auth, request));
- }
- async function signInWithEmailLinkForLinking(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithEmailLink" /* Endpoint.SIGN_IN_WITH_EMAIL_LINK */, _addTidIfNecessary(auth, request));
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Interface that represents the credentials returned by {@link EmailAuthProvider} for
- * {@link ProviderId}.PASSWORD
- *
- * @remarks
- * Covers both {@link SignInMethod}.EMAIL_PASSWORD and
- * {@link SignInMethod}.EMAIL_LINK.
- *
- * @public
- */
- class EmailAuthCredential extends AuthCredential {
- /** @internal */
- constructor(
- /** @internal */
- _email,
- /** @internal */
- _password, signInMethod,
- /** @internal */
- _tenantId = null) {
- super("password" /* ProviderId.PASSWORD */, signInMethod);
- this._email = _email;
- this._password = _password;
- this._tenantId = _tenantId;
- }
- /** @internal */
- static _fromEmailAndPassword(email, password) {
- return new EmailAuthCredential(email, password, "password" /* SignInMethod.EMAIL_PASSWORD */);
- }
- /** @internal */
- static _fromEmailAndCode(email, oobCode, tenantId = null) {
- return new EmailAuthCredential(email, oobCode, "emailLink" /* SignInMethod.EMAIL_LINK */, tenantId);
- }
- /** {@inheritdoc AuthCredential.toJSON} */
- toJSON() {
- return {
- email: this._email,
- password: this._password,
- signInMethod: this.signInMethod,
- tenantId: this._tenantId
- };
- }
- /**
- * Static method to deserialize a JSON representation of an object into an {@link AuthCredential}.
- *
- * @param json - Either `object` or the stringified representation of the object. When string is
- * provided, `JSON.parse` would be called first.
- *
- * @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
- */
- static fromJSON(json) {
- const obj = typeof json === 'string' ? JSON.parse(json) : json;
- if ((obj === null || obj === void 0 ? void 0 : obj.email) && (obj === null || obj === void 0 ? void 0 : obj.password)) {
- if (obj.signInMethod === "password" /* SignInMethod.EMAIL_PASSWORD */) {
- return this._fromEmailAndPassword(obj.email, obj.password);
- }
- else if (obj.signInMethod === "emailLink" /* SignInMethod.EMAIL_LINK */) {
- return this._fromEmailAndCode(obj.email, obj.password, obj.tenantId);
- }
- }
- return null;
- }
- /** @internal */
- async _getIdTokenResponse(auth) {
- var _a;
- switch (this.signInMethod) {
- case "password" /* SignInMethod.EMAIL_PASSWORD */:
- const request = {
- returnSecureToken: true,
- email: this._email,
- password: this._password,
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */
- };
- if ((_a = auth._getRecaptchaConfig()) === null || _a === void 0 ? void 0 : _a.emailPasswordEnabled) {
- const requestWithRecaptcha = await injectRecaptchaFields(auth, request, "signInWithPassword" /* RecaptchaActionName.SIGN_IN_WITH_PASSWORD */);
- return signInWithPassword(auth, requestWithRecaptcha);
- }
- else {
- return signInWithPassword(auth, request).catch(async (error) => {
- if (error.code === `auth/${"missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */}`) {
- console.log('Sign-in with email address and password is protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the sign-in flow.');
- const requestWithRecaptcha = await injectRecaptchaFields(auth, request, "signInWithPassword" /* RecaptchaActionName.SIGN_IN_WITH_PASSWORD */);
- return signInWithPassword(auth, requestWithRecaptcha);
- }
- else {
- return Promise.reject(error);
- }
- });
- }
- case "emailLink" /* SignInMethod.EMAIL_LINK */:
- return signInWithEmailLink$1(auth, {
- email: this._email,
- oobCode: this._password
- });
- default:
- _fail(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- }
- /** @internal */
- async _linkToIdToken(auth, idToken) {
- switch (this.signInMethod) {
- case "password" /* SignInMethod.EMAIL_PASSWORD */:
- return updateEmailPassword(auth, {
- idToken,
- returnSecureToken: true,
- email: this._email,
- password: this._password
- });
- case "emailLink" /* SignInMethod.EMAIL_LINK */:
- return signInWithEmailLinkForLinking(auth, {
- idToken,
- email: this._email,
- oobCode: this._password
- });
- default:
- _fail(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- }
- /** @internal */
- _getReauthenticationResolver(auth) {
- return this._getIdTokenResponse(auth);
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function signInWithIdp(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithIdp" /* Endpoint.SIGN_IN_WITH_IDP */, _addTidIfNecessary(auth, request));
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const IDP_REQUEST_URI$1 = 'http://localhost';
- /**
- * Represents the OAuth credentials returned by an {@link OAuthProvider}.
- *
- * @remarks
- * Implementations specify the details about each auth provider's credential requirements.
- *
- * @public
- */
- class OAuthCredential extends AuthCredential {
- constructor() {
- super(...arguments);
- this.pendingToken = null;
- }
- /** @internal */
- static _fromParams(params) {
- const cred = new OAuthCredential(params.providerId, params.signInMethod);
- if (params.idToken || params.accessToken) {
- // OAuth 2 and either ID token or access token.
- if (params.idToken) {
- cred.idToken = params.idToken;
- }
- if (params.accessToken) {
- cred.accessToken = params.accessToken;
- }
- // Add nonce if available and no pendingToken is present.
- if (params.nonce && !params.pendingToken) {
- cred.nonce = params.nonce;
- }
- if (params.pendingToken) {
- cred.pendingToken = params.pendingToken;
- }
- }
- else if (params.oauthToken && params.oauthTokenSecret) {
- // OAuth 1 and OAuth token with token secret
- cred.accessToken = params.oauthToken;
- cred.secret = params.oauthTokenSecret;
- }
- else {
- _fail("argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- }
- return cred;
- }
- /** {@inheritdoc AuthCredential.toJSON} */
- toJSON() {
- return {
- idToken: this.idToken,
- accessToken: this.accessToken,
- secret: this.secret,
- nonce: this.nonce,
- pendingToken: this.pendingToken,
- providerId: this.providerId,
- signInMethod: this.signInMethod
- };
- }
- /**
- * Static method to deserialize a JSON representation of an object into an
- * {@link AuthCredential}.
- *
- * @param json - Input can be either Object or the stringified representation of the object.
- * When string is provided, JSON.parse would be called first.
- *
- * @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
- */
- static fromJSON(json) {
- const obj = typeof json === 'string' ? JSON.parse(json) : json;
- const { providerId, signInMethod } = obj, rest = __rest(obj, ["providerId", "signInMethod"]);
- if (!providerId || !signInMethod) {
- return null;
- }
- const cred = new OAuthCredential(providerId, signInMethod);
- cred.idToken = rest.idToken || undefined;
- cred.accessToken = rest.accessToken || undefined;
- cred.secret = rest.secret;
- cred.nonce = rest.nonce;
- cred.pendingToken = rest.pendingToken || null;
- return cred;
- }
- /** @internal */
- _getIdTokenResponse(auth) {
- const request = this.buildRequest();
- return signInWithIdp(auth, request);
- }
- /** @internal */
- _linkToIdToken(auth, idToken) {
- const request = this.buildRequest();
- request.idToken = idToken;
- return signInWithIdp(auth, request);
- }
- /** @internal */
- _getReauthenticationResolver(auth) {
- const request = this.buildRequest();
- request.autoCreate = false;
- return signInWithIdp(auth, request);
- }
- buildRequest() {
- const request = {
- requestUri: IDP_REQUEST_URI$1,
- returnSecureToken: true
- };
- if (this.pendingToken) {
- request.pendingToken = this.pendingToken;
- }
- else {
- const postBody = {};
- if (this.idToken) {
- postBody['id_token'] = this.idToken;
- }
- if (this.accessToken) {
- postBody['access_token'] = this.accessToken;
- }
- if (this.secret) {
- postBody['oauth_token_secret'] = this.secret;
- }
- postBody['providerId'] = this.providerId;
- if (this.nonce && !this.pendingToken) {
- postBody['nonce'] = this.nonce;
- }
- request.postBody = querystring(postBody);
- }
- return request;
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function sendPhoneVerificationCode(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:sendVerificationCode" /* Endpoint.SEND_VERIFICATION_CODE */, _addTidIfNecessary(auth, request));
- }
- async function signInWithPhoneNumber$1(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithPhoneNumber" /* Endpoint.SIGN_IN_WITH_PHONE_NUMBER */, _addTidIfNecessary(auth, request));
- }
- async function linkWithPhoneNumber$1(auth, request) {
- const response = await _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithPhoneNumber" /* Endpoint.SIGN_IN_WITH_PHONE_NUMBER */, _addTidIfNecessary(auth, request));
- if (response.temporaryProof) {
- throw _makeTaggedError(auth, "account-exists-with-different-credential" /* AuthErrorCode.NEED_CONFIRMATION */, response);
- }
- return response;
- }
- const VERIFY_PHONE_NUMBER_FOR_EXISTING_ERROR_MAP_ = {
- ["USER_NOT_FOUND" /* ServerError.USER_NOT_FOUND */]: "user-not-found" /* AuthErrorCode.USER_DELETED */
- };
- async function verifyPhoneNumberForExisting(auth, request) {
- const apiRequest = Object.assign(Object.assign({}, request), { operation: 'REAUTH' });
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithPhoneNumber" /* Endpoint.SIGN_IN_WITH_PHONE_NUMBER */, _addTidIfNecessary(auth, apiRequest), VERIFY_PHONE_NUMBER_FOR_EXISTING_ERROR_MAP_);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Represents the credentials returned by {@link PhoneAuthProvider}.
- *
- * @public
- */
- class PhoneAuthCredential extends AuthCredential {
- constructor(params) {
- super("phone" /* ProviderId.PHONE */, "phone" /* SignInMethod.PHONE */);
- this.params = params;
- }
- /** @internal */
- static _fromVerification(verificationId, verificationCode) {
- return new PhoneAuthCredential({ verificationId, verificationCode });
- }
- /** @internal */
- static _fromTokenResponse(phoneNumber, temporaryProof) {
- return new PhoneAuthCredential({ phoneNumber, temporaryProof });
- }
- /** @internal */
- _getIdTokenResponse(auth) {
- return signInWithPhoneNumber$1(auth, this._makeVerificationRequest());
- }
- /** @internal */
- _linkToIdToken(auth, idToken) {
- return linkWithPhoneNumber$1(auth, Object.assign({ idToken }, this._makeVerificationRequest()));
- }
- /** @internal */
- _getReauthenticationResolver(auth) {
- return verifyPhoneNumberForExisting(auth, this._makeVerificationRequest());
- }
- /** @internal */
- _makeVerificationRequest() {
- const { temporaryProof, phoneNumber, verificationId, verificationCode } = this.params;
- if (temporaryProof && phoneNumber) {
- return { temporaryProof, phoneNumber };
- }
- return {
- sessionInfo: verificationId,
- code: verificationCode
- };
- }
- /** {@inheritdoc AuthCredential.toJSON} */
- toJSON() {
- const obj = {
- providerId: this.providerId
- };
- if (this.params.phoneNumber) {
- obj.phoneNumber = this.params.phoneNumber;
- }
- if (this.params.temporaryProof) {
- obj.temporaryProof = this.params.temporaryProof;
- }
- if (this.params.verificationCode) {
- obj.verificationCode = this.params.verificationCode;
- }
- if (this.params.verificationId) {
- obj.verificationId = this.params.verificationId;
- }
- return obj;
- }
- /** Generates a phone credential based on a plain object or a JSON string. */
- static fromJSON(json) {
- if (typeof json === 'string') {
- json = JSON.parse(json);
- }
- const { verificationId, verificationCode, phoneNumber, temporaryProof } = json;
- if (!verificationCode &&
- !verificationId &&
- !phoneNumber &&
- !temporaryProof) {
- return null;
- }
- return new PhoneAuthCredential({
- verificationId,
- verificationCode,
- phoneNumber,
- temporaryProof
- });
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Maps the mode string in action code URL to Action Code Info operation.
- *
- * @param mode
- */
- function parseMode(mode) {
- switch (mode) {
- case 'recoverEmail':
- return "RECOVER_EMAIL" /* ActionCodeOperation.RECOVER_EMAIL */;
- case 'resetPassword':
- return "PASSWORD_RESET" /* ActionCodeOperation.PASSWORD_RESET */;
- case 'signIn':
- return "EMAIL_SIGNIN" /* ActionCodeOperation.EMAIL_SIGNIN */;
- case 'verifyEmail':
- return "VERIFY_EMAIL" /* ActionCodeOperation.VERIFY_EMAIL */;
- case 'verifyAndChangeEmail':
- return "VERIFY_AND_CHANGE_EMAIL" /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */;
- case 'revertSecondFactorAddition':
- return "REVERT_SECOND_FACTOR_ADDITION" /* ActionCodeOperation.REVERT_SECOND_FACTOR_ADDITION */;
- default:
- return null;
- }
- }
- /**
- * Helper to parse FDL links
- *
- * @param url
- */
- function parseDeepLink(url) {
- const link = querystringDecode(extractQuerystring(url))['link'];
- // Double link case (automatic redirect).
- const doubleDeepLink = link
- ? querystringDecode(extractQuerystring(link))['deep_link_id']
- : null;
- // iOS custom scheme links.
- const iOSDeepLink = querystringDecode(extractQuerystring(url))['deep_link_id'];
- const iOSDoubleDeepLink = iOSDeepLink
- ? querystringDecode(extractQuerystring(iOSDeepLink))['link']
- : null;
- return iOSDoubleDeepLink || iOSDeepLink || doubleDeepLink || link || url;
- }
- /**
- * A utility class to parse email action URLs such as password reset, email verification,
- * email link sign in, etc.
- *
- * @public
- */
- class ActionCodeURL {
- /**
- * @param actionLink - The link from which to extract the URL.
- * @returns The {@link ActionCodeURL} object, or null if the link is invalid.
- *
- * @internal
- */
- constructor(actionLink) {
- var _a, _b, _c, _d, _e, _f;
- const searchParams = querystringDecode(extractQuerystring(actionLink));
- const apiKey = (_a = searchParams["apiKey" /* QueryField.API_KEY */]) !== null && _a !== void 0 ? _a : null;
- const code = (_b = searchParams["oobCode" /* QueryField.CODE */]) !== null && _b !== void 0 ? _b : null;
- const operation = parseMode((_c = searchParams["mode" /* QueryField.MODE */]) !== null && _c !== void 0 ? _c : null);
- // Validate API key, code and mode.
- _assert$4(apiKey && code && operation, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- this.apiKey = apiKey;
- this.operation = operation;
- this.code = code;
- this.continueUrl = (_d = searchParams["continueUrl" /* QueryField.CONTINUE_URL */]) !== null && _d !== void 0 ? _d : null;
- this.languageCode = (_e = searchParams["languageCode" /* QueryField.LANGUAGE_CODE */]) !== null && _e !== void 0 ? _e : null;
- this.tenantId = (_f = searchParams["tenantId" /* QueryField.TENANT_ID */]) !== null && _f !== void 0 ? _f : null;
- }
- /**
- * Parses the email action link string and returns an {@link ActionCodeURL} if the link is valid,
- * otherwise returns null.
- *
- * @param link - The email action link string.
- * @returns The {@link ActionCodeURL} object, or null if the link is invalid.
- *
- * @public
- */
- static parseLink(link) {
- const actionLink = parseDeepLink(link);
- try {
- return new ActionCodeURL(actionLink);
- }
- catch (_a) {
- return null;
- }
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating {@link EmailAuthCredential}.
- *
- * @public
- */
- class EmailAuthProvider {
- constructor() {
- /**
- * Always set to {@link ProviderId}.PASSWORD, even for email link.
- */
- this.providerId = EmailAuthProvider.PROVIDER_ID;
- }
- /**
- * Initialize an {@link AuthCredential} using an email and password.
- *
- * @example
- * ```javascript
- * const authCredential = EmailAuthProvider.credential(email, password);
- * const userCredential = await signInWithCredential(auth, authCredential);
- * ```
- *
- * @example
- * ```javascript
- * const userCredential = await signInWithEmailAndPassword(auth, email, password);
- * ```
- *
- * @param email - Email address.
- * @param password - User account password.
- * @returns The auth provider credential.
- */
- static credential(email, password) {
- return EmailAuthCredential._fromEmailAndPassword(email, password);
- }
- /**
- * Initialize an {@link AuthCredential} using an email and an email link after a sign in with
- * email link operation.
- *
- * @example
- * ```javascript
- * const authCredential = EmailAuthProvider.credentialWithLink(auth, email, emailLink);
- * const userCredential = await signInWithCredential(auth, authCredential);
- * ```
- *
- * @example
- * ```javascript
- * await sendSignInLinkToEmail(auth, email);
- * // Obtain emailLink from user.
- * const userCredential = await signInWithEmailLink(auth, email, emailLink);
- * ```
- *
- * @param auth - The {@link Auth} instance used to verify the link.
- * @param email - Email address.
- * @param emailLink - Sign-in email link.
- * @returns - The auth provider credential.
- */
- static credentialWithLink(email, emailLink) {
- const actionCodeUrl = ActionCodeURL.parseLink(emailLink);
- _assert$4(actionCodeUrl, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- return EmailAuthCredential._fromEmailAndCode(email, actionCodeUrl.code, actionCodeUrl.tenantId);
- }
- }
- /**
- * Always set to {@link ProviderId}.PASSWORD, even for email link.
- */
- EmailAuthProvider.PROVIDER_ID = "password" /* ProviderId.PASSWORD */;
- /**
- * Always set to {@link SignInMethod}.EMAIL_PASSWORD.
- */
- EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD = "password" /* SignInMethod.EMAIL_PASSWORD */;
- /**
- * Always set to {@link SignInMethod}.EMAIL_LINK.
- */
- EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD = "emailLink" /* SignInMethod.EMAIL_LINK */;
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * The base class for all Federated providers (OAuth (including OIDC), SAML).
- *
- * This class is not meant to be instantiated directly.
- *
- * @public
- */
- class FederatedAuthProvider {
- /**
- * Constructor for generic OAuth providers.
- *
- * @param providerId - Provider for which credentials should be generated.
- */
- constructor(providerId) {
- this.providerId = providerId;
- /** @internal */
- this.defaultLanguageCode = null;
- /** @internal */
- this.customParameters = {};
- }
- /**
- * Set the language gode.
- *
- * @param languageCode - language code
- */
- setDefaultLanguage(languageCode) {
- this.defaultLanguageCode = languageCode;
- }
- /**
- * Sets the OAuth custom parameters to pass in an OAuth request for popup and redirect sign-in
- * operations.
- *
- * @remarks
- * For a detailed list, check the reserved required OAuth 2.0 parameters such as `client_id`,
- * `redirect_uri`, `scope`, `response_type`, and `state` are not allowed and will be ignored.
- *
- * @param customOAuthParameters - The custom OAuth parameters to pass in the OAuth request.
- */
- setCustomParameters(customOAuthParameters) {
- this.customParameters = customOAuthParameters;
- return this;
- }
- /**
- * Retrieve the current list of {@link CustomParameters}.
- */
- getCustomParameters() {
- return this.customParameters;
- }
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Common code to all OAuth providers. This is separate from the
- * {@link OAuthProvider} so that child providers (like
- * {@link GoogleAuthProvider}) don't inherit the `credential` instance method.
- * Instead, they rely on a static `credential` method.
- */
- class BaseOAuthProvider extends FederatedAuthProvider {
- constructor() {
- super(...arguments);
- /** @internal */
- this.scopes = [];
- }
- /**
- * Add an OAuth scope to the credential.
- *
- * @param scope - Provider OAuth scope to add.
- */
- addScope(scope) {
- // If not already added, add scope to list.
- if (!this.scopes.includes(scope)) {
- this.scopes.push(scope);
- }
- return this;
- }
- /**
- * Retrieve the current list of OAuth scopes.
- */
- getScopes() {
- return [...this.scopes];
- }
- }
- /**
- * Provider for generating generic {@link OAuthCredential}.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new OAuthProvider('google.com');
- * // Start a sign in process for an unauthenticated user.
- * provider.addScope('profile');
- * provider.addScope('email');
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a OAuth Access Token for the provider.
- * const credential = provider.credentialFromResult(auth, result);
- * const token = credential.accessToken;
- * }
- * ```
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new OAuthProvider('google.com');
- * provider.addScope('profile');
- * provider.addScope('email');
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a OAuth Access Token for the provider.
- * const credential = provider.credentialFromResult(auth, result);
- * const token = credential.accessToken;
- * ```
- * @public
- */
- class OAuthProvider extends BaseOAuthProvider {
- /**
- * Creates an {@link OAuthCredential} from a JSON string or a plain object.
- * @param json - A plain object or a JSON string
- */
- static credentialFromJSON(json) {
- const obj = typeof json === 'string' ? JSON.parse(json) : json;
- _assert$4('providerId' in obj && 'signInMethod' in obj, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- return OAuthCredential._fromParams(obj);
- }
- /**
- * Creates a {@link OAuthCredential} from a generic OAuth provider's access token or ID token.
- *
- * @remarks
- * The raw nonce is required when an ID token with a nonce field is provided. The SHA-256 hash of
- * the raw nonce must match the nonce field in the ID token.
- *
- * @example
- * ```javascript
- * // `googleUser` from the onsuccess Google Sign In callback.
- * // Initialize a generate OAuth provider with a `google.com` providerId.
- * const provider = new OAuthProvider('google.com');
- * const credential = provider.credential({
- * idToken: googleUser.getAuthResponse().id_token,
- * });
- * const result = await signInWithCredential(credential);
- * ```
- *
- * @param params - Either the options object containing the ID token, access token and raw nonce
- * or the ID token string.
- */
- credential(params) {
- return this._credential(Object.assign(Object.assign({}, params), { nonce: params.rawNonce }));
- }
- /** An internal credential method that accepts more permissive options */
- _credential(params) {
- _assert$4(params.idToken || params.accessToken, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- // For OAuthCredential, sign in method is same as providerId.
- return OAuthCredential._fromParams(Object.assign(Object.assign({}, params), { providerId: this.providerId, signInMethod: this.providerId }));
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return OAuthProvider.oauthCredentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return OAuthProvider.oauthCredentialFromTaggedObject((error.customData || {}));
- }
- static oauthCredentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse) {
- return null;
- }
- const { oauthIdToken, oauthAccessToken, oauthTokenSecret, pendingToken, nonce, providerId } = tokenResponse;
- if (!oauthAccessToken &&
- !oauthTokenSecret &&
- !oauthIdToken &&
- !pendingToken) {
- return null;
- }
- if (!providerId) {
- return null;
- }
- try {
- return new OAuthProvider(providerId)._credential({
- idToken: oauthIdToken,
- accessToken: oauthAccessToken,
- nonce,
- pendingToken
- });
- }
- catch (e) {
- return null;
- }
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.FACEBOOK.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new FacebookAuthProvider();
- * // Start a sign in process for an unauthenticated user.
- * provider.addScope('user_birthday');
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Facebook Access Token.
- * const credential = FacebookAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * }
- * ```
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new FacebookAuthProvider();
- * provider.addScope('user_birthday');
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a Facebook Access Token.
- * const credential = FacebookAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * ```
- *
- * @public
- */
- class FacebookAuthProvider extends BaseOAuthProvider {
- constructor() {
- super("facebook.com" /* ProviderId.FACEBOOK */);
- }
- /**
- * Creates a credential for Facebook.
- *
- * @example
- * ```javascript
- * // `event` from the Facebook auth.authResponseChange callback.
- * const credential = FacebookAuthProvider.credential(event.authResponse.accessToken);
- * const result = await signInWithCredential(credential);
- * ```
- *
- * @param accessToken - Facebook access token.
- */
- static credential(accessToken) {
- return OAuthCredential._fromParams({
- providerId: FacebookAuthProvider.PROVIDER_ID,
- signInMethod: FacebookAuthProvider.FACEBOOK_SIGN_IN_METHOD,
- accessToken
- });
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return FacebookAuthProvider.credentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return FacebookAuthProvider.credentialFromTaggedObject((error.customData || {}));
- }
- static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse || !('oauthAccessToken' in tokenResponse)) {
- return null;
- }
- if (!tokenResponse.oauthAccessToken) {
- return null;
- }
- try {
- return FacebookAuthProvider.credential(tokenResponse.oauthAccessToken);
- }
- catch (_a) {
- return null;
- }
- }
- }
- /** Always set to {@link SignInMethod}.FACEBOOK. */
- FacebookAuthProvider.FACEBOOK_SIGN_IN_METHOD = "facebook.com" /* SignInMethod.FACEBOOK */;
- /** Always set to {@link ProviderId}.FACEBOOK. */
- FacebookAuthProvider.PROVIDER_ID = "facebook.com" /* ProviderId.FACEBOOK */;
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating an an {@link OAuthCredential} for {@link ProviderId}.GOOGLE.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new GoogleAuthProvider();
- * // Start a sign in process for an unauthenticated user.
- * provider.addScope('profile');
- * provider.addScope('email');
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Google Access Token.
- * const credential = GoogleAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * }
- * ```
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new GoogleAuthProvider();
- * provider.addScope('profile');
- * provider.addScope('email');
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a Google Access Token.
- * const credential = GoogleAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * ```
- *
- * @public
- */
- class GoogleAuthProvider extends BaseOAuthProvider {
- constructor() {
- super("google.com" /* ProviderId.GOOGLE */);
- this.addScope('profile');
- }
- /**
- * Creates a credential for Google. At least one of ID token and access token is required.
- *
- * @example
- * ```javascript
- * // \`googleUser\` from the onsuccess Google Sign In callback.
- * const credential = GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token);
- * const result = await signInWithCredential(credential);
- * ```
- *
- * @param idToken - Google ID token.
- * @param accessToken - Google access token.
- */
- static credential(idToken, accessToken) {
- return OAuthCredential._fromParams({
- providerId: GoogleAuthProvider.PROVIDER_ID,
- signInMethod: GoogleAuthProvider.GOOGLE_SIGN_IN_METHOD,
- idToken,
- accessToken
- });
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return GoogleAuthProvider.credentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return GoogleAuthProvider.credentialFromTaggedObject((error.customData || {}));
- }
- static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse) {
- return null;
- }
- const { oauthIdToken, oauthAccessToken } = tokenResponse;
- if (!oauthIdToken && !oauthAccessToken) {
- // This could be an oauth 1 credential or a phone credential
- return null;
- }
- try {
- return GoogleAuthProvider.credential(oauthIdToken, oauthAccessToken);
- }
- catch (_a) {
- return null;
- }
- }
- }
- /** Always set to {@link SignInMethod}.GOOGLE. */
- GoogleAuthProvider.GOOGLE_SIGN_IN_METHOD = "google.com" /* SignInMethod.GOOGLE */;
- /** Always set to {@link ProviderId}.GOOGLE. */
- GoogleAuthProvider.PROVIDER_ID = "google.com" /* ProviderId.GOOGLE */;
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.GITHUB.
- *
- * @remarks
- * GitHub requires an OAuth 2.0 redirect, so you can either handle the redirect directly, or use
- * the {@link signInWithPopup} handler:
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new GithubAuthProvider();
- * // Start a sign in process for an unauthenticated user.
- * provider.addScope('repo');
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Github Access Token.
- * const credential = GithubAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * }
- * ```
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new GithubAuthProvider();
- * provider.addScope('repo');
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a Github Access Token.
- * const credential = GithubAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * ```
- * @public
- */
- class GithubAuthProvider extends BaseOAuthProvider {
- constructor() {
- super("github.com" /* ProviderId.GITHUB */);
- }
- /**
- * Creates a credential for Github.
- *
- * @param accessToken - Github access token.
- */
- static credential(accessToken) {
- return OAuthCredential._fromParams({
- providerId: GithubAuthProvider.PROVIDER_ID,
- signInMethod: GithubAuthProvider.GITHUB_SIGN_IN_METHOD,
- accessToken
- });
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return GithubAuthProvider.credentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return GithubAuthProvider.credentialFromTaggedObject((error.customData || {}));
- }
- static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse || !('oauthAccessToken' in tokenResponse)) {
- return null;
- }
- if (!tokenResponse.oauthAccessToken) {
- return null;
- }
- try {
- return GithubAuthProvider.credential(tokenResponse.oauthAccessToken);
- }
- catch (_a) {
- return null;
- }
- }
- }
- /** Always set to {@link SignInMethod}.GITHUB. */
- GithubAuthProvider.GITHUB_SIGN_IN_METHOD = "github.com" /* SignInMethod.GITHUB */;
- /** Always set to {@link ProviderId}.GITHUB. */
- GithubAuthProvider.PROVIDER_ID = "github.com" /* ProviderId.GITHUB */;
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const IDP_REQUEST_URI = 'http://localhost';
- /**
- * @public
- */
- class SAMLAuthCredential extends AuthCredential {
- /** @internal */
- constructor(providerId, pendingToken) {
- super(providerId, providerId);
- this.pendingToken = pendingToken;
- }
- /** @internal */
- _getIdTokenResponse(auth) {
- const request = this.buildRequest();
- return signInWithIdp(auth, request);
- }
- /** @internal */
- _linkToIdToken(auth, idToken) {
- const request = this.buildRequest();
- request.idToken = idToken;
- return signInWithIdp(auth, request);
- }
- /** @internal */
- _getReauthenticationResolver(auth) {
- const request = this.buildRequest();
- request.autoCreate = false;
- return signInWithIdp(auth, request);
- }
- /** {@inheritdoc AuthCredential.toJSON} */
- toJSON() {
- return {
- signInMethod: this.signInMethod,
- providerId: this.providerId,
- pendingToken: this.pendingToken
- };
- }
- /**
- * Static method to deserialize a JSON representation of an object into an
- * {@link AuthCredential}.
- *
- * @param json - Input can be either Object or the stringified representation of the object.
- * When string is provided, JSON.parse would be called first.
- *
- * @returns If the JSON input does not represent an {@link AuthCredential}, null is returned.
- */
- static fromJSON(json) {
- const obj = typeof json === 'string' ? JSON.parse(json) : json;
- const { providerId, signInMethod, pendingToken } = obj;
- if (!providerId ||
- !signInMethod ||
- !pendingToken ||
- providerId !== signInMethod) {
- return null;
- }
- return new SAMLAuthCredential(providerId, pendingToken);
- }
- /**
- * Helper static method to avoid exposing the constructor to end users.
- *
- * @internal
- */
- static _create(providerId, pendingToken) {
- return new SAMLAuthCredential(providerId, pendingToken);
- }
- buildRequest() {
- return {
- requestUri: IDP_REQUEST_URI,
- returnSecureToken: true,
- pendingToken: this.pendingToken
- };
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const SAML_PROVIDER_PREFIX = 'saml.';
- /**
- * An {@link AuthProvider} for SAML.
- *
- * @public
- */
- class SAMLAuthProvider extends FederatedAuthProvider {
- /**
- * Constructor. The providerId must start with "saml."
- * @param providerId - SAML provider ID.
- */
- constructor(providerId) {
- _assert$4(providerId.startsWith(SAML_PROVIDER_PREFIX), "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- super(providerId);
- }
- /**
- * Generates an {@link AuthCredential} from a {@link UserCredential} after a
- * successful SAML flow completes.
- *
- * @remarks
- *
- * For example, to get an {@link AuthCredential}, you could write the
- * following code:
- *
- * ```js
- * const userCredential = await signInWithPopup(auth, samlProvider);
- * const credential = SAMLAuthProvider.credentialFromResult(userCredential);
- * ```
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return SAMLAuthProvider.samlCredentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return SAMLAuthProvider.samlCredentialFromTaggedObject((error.customData || {}));
- }
- /**
- * Creates an {@link AuthCredential} from a JSON string or a plain object.
- * @param json - A plain object or a JSON string
- */
- static credentialFromJSON(json) {
- const credential = SAMLAuthCredential.fromJSON(json);
- _assert$4(credential, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- return credential;
- }
- static samlCredentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse) {
- return null;
- }
- const { pendingToken, providerId } = tokenResponse;
- if (!pendingToken || !providerId) {
- return null;
- }
- try {
- return SAMLAuthCredential._create(providerId, pendingToken);
- }
- catch (e) {
- return null;
- }
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.TWITTER.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new TwitterAuthProvider();
- * // Start a sign in process for an unauthenticated user.
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Twitter Access Token and Secret.
- * const credential = TwitterAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * const secret = credential.secret;
- * }
- * ```
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new TwitterAuthProvider();
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a Twitter Access Token and Secret.
- * const credential = TwitterAuthProvider.credentialFromResult(result);
- * const token = credential.accessToken;
- * const secret = credential.secret;
- * ```
- *
- * @public
- */
- class TwitterAuthProvider extends BaseOAuthProvider {
- constructor() {
- super("twitter.com" /* ProviderId.TWITTER */);
- }
- /**
- * Creates a credential for Twitter.
- *
- * @param token - Twitter access token.
- * @param secret - Twitter secret.
- */
- static credential(token, secret) {
- return OAuthCredential._fromParams({
- providerId: TwitterAuthProvider.PROVIDER_ID,
- signInMethod: TwitterAuthProvider.TWITTER_SIGN_IN_METHOD,
- oauthToken: token,
- oauthTokenSecret: secret
- });
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- return TwitterAuthProvider.credentialFromTaggedObject(userCredential);
- }
- /**
- * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was
- * thrown during a sign-in, link, or reauthenticate operation.
- *
- * @param userCredential - The user credential.
- */
- static credentialFromError(error) {
- return TwitterAuthProvider.credentialFromTaggedObject((error.customData || {}));
- }
- static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse) {
- return null;
- }
- const { oauthAccessToken, oauthTokenSecret } = tokenResponse;
- if (!oauthAccessToken || !oauthTokenSecret) {
- return null;
- }
- try {
- return TwitterAuthProvider.credential(oauthAccessToken, oauthTokenSecret);
- }
- catch (_a) {
- return null;
- }
- }
- }
- /** Always set to {@link SignInMethod}.TWITTER. */
- TwitterAuthProvider.TWITTER_SIGN_IN_METHOD = "twitter.com" /* SignInMethod.TWITTER */;
- /** Always set to {@link ProviderId}.TWITTER. */
- TwitterAuthProvider.PROVIDER_ID = "twitter.com" /* ProviderId.TWITTER */;
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function signUp(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signUp" /* Endpoint.SIGN_UP */, _addTidIfNecessary(auth, request));
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class UserCredentialImpl {
- constructor(params) {
- this.user = params.user;
- this.providerId = params.providerId;
- this._tokenResponse = params._tokenResponse;
- this.operationType = params.operationType;
- }
- static async _fromIdTokenResponse(auth, operationType, idTokenResponse, isAnonymous = false) {
- const user = await UserImpl._fromIdTokenResponse(auth, idTokenResponse, isAnonymous);
- const providerId = providerIdForResponse(idTokenResponse);
- const userCred = new UserCredentialImpl({
- user,
- providerId,
- _tokenResponse: idTokenResponse,
- operationType
- });
- return userCred;
- }
- static async _forOperation(user, operationType, response) {
- await user._updateTokensIfNecessary(response, /* reload */ true);
- const providerId = providerIdForResponse(response);
- return new UserCredentialImpl({
- user,
- providerId,
- _tokenResponse: response,
- operationType
- });
- }
- }
- function providerIdForResponse(response) {
- if (response.providerId) {
- return response.providerId;
- }
- if ('phoneNumber' in response) {
- return "phone" /* ProviderId.PHONE */;
- }
- return null;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Asynchronously signs in as an anonymous user.
- *
- * @remarks
- * If there is already an anonymous user signed in, that user will be returned; otherwise, a
- * new anonymous user identity will be created and returned.
- *
- * @param auth - The {@link Auth} instance.
- *
- * @public
- */
- async function signInAnonymously(auth) {
- var _a;
- const authInternal = _castAuth(auth);
- await authInternal._initializationPromise;
- if ((_a = authInternal.currentUser) === null || _a === void 0 ? void 0 : _a.isAnonymous) {
- // If an anonymous user is already signed in, no need to sign them in again.
- return new UserCredentialImpl({
- user: authInternal.currentUser,
- providerId: null,
- operationType: "signIn" /* OperationType.SIGN_IN */
- });
- }
- const response = await signUp(authInternal, {
- returnSecureToken: true
- });
- const userCredential = await UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn" /* OperationType.SIGN_IN */, response, true);
- await authInternal._updateCurrentUser(userCredential.user);
- return userCredential;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class MultiFactorError extends FirebaseError {
- constructor(auth, error, operationType, user) {
- var _a;
- super(error.code, error.message);
- this.operationType = operationType;
- this.user = user;
- // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
- Object.setPrototypeOf(this, MultiFactorError.prototype);
- this.customData = {
- appName: auth.name,
- tenantId: (_a = auth.tenantId) !== null && _a !== void 0 ? _a : undefined,
- _serverResponse: error.customData._serverResponse,
- operationType
- };
- }
- static _fromErrorAndOperation(auth, error, operationType, user) {
- return new MultiFactorError(auth, error, operationType, user);
- }
- }
- function _processCredentialSavingMfaContextIfNecessary(auth, operationType, credential, user) {
- const idTokenProvider = operationType === "reauthenticate" /* OperationType.REAUTHENTICATE */
- ? credential._getReauthenticationResolver(auth)
- : credential._getIdTokenResponse(auth);
- return idTokenProvider.catch(error => {
- if (error.code === `auth/${"multi-factor-auth-required" /* AuthErrorCode.MFA_REQUIRED */}`) {
- throw MultiFactorError._fromErrorAndOperation(auth, error, operationType, user);
- }
- throw error;
- });
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Takes a set of UserInfo provider data and converts it to a set of names
- */
- function providerDataAsNames(providerData) {
- return new Set(providerData
- .map(({ providerId }) => providerId)
- .filter(pid => !!pid));
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Unlinks a provider from a user account.
- *
- * @param user - The user.
- * @param providerId - The provider to unlink.
- *
- * @public
- */
- async function unlink(user, providerId) {
- const userInternal = getModularInstance(user);
- await _assertLinkedStatus(true, userInternal, providerId);
- const { providerUserInfo } = await deleteLinkedAccounts(userInternal.auth, {
- idToken: await userInternal.getIdToken(),
- deleteProvider: [providerId]
- });
- const providersLeft = providerDataAsNames(providerUserInfo || []);
- userInternal.providerData = userInternal.providerData.filter(pd => providersLeft.has(pd.providerId));
- if (!providersLeft.has("phone" /* ProviderId.PHONE */)) {
- userInternal.phoneNumber = null;
- }
- await userInternal.auth._persistUserIfCurrent(userInternal);
- return userInternal;
- }
- async function _link$1(user, credential, bypassAuthState = false) {
- const response = await _logoutIfInvalidated(user, credential._linkToIdToken(user.auth, await user.getIdToken()), bypassAuthState);
- return UserCredentialImpl._forOperation(user, "link" /* OperationType.LINK */, response);
- }
- async function _assertLinkedStatus(expected, user, provider) {
- await _reloadWithoutSaving(user);
- const providerIds = providerDataAsNames(user.providerData);
- const code = expected === false
- ? "provider-already-linked" /* AuthErrorCode.PROVIDER_ALREADY_LINKED */
- : "no-such-provider" /* AuthErrorCode.NO_SUCH_PROVIDER */;
- _assert$4(providerIds.has(provider) === expected, user.auth, code);
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function _reauthenticate(user, credential, bypassAuthState = false) {
- const { auth } = user;
- const operationType = "reauthenticate" /* OperationType.REAUTHENTICATE */;
- try {
- const response = await _logoutIfInvalidated(user, _processCredentialSavingMfaContextIfNecessary(auth, operationType, credential, user), bypassAuthState);
- _assert$4(response.idToken, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const parsed = _parseToken(response.idToken);
- _assert$4(parsed, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const { sub: localId } = parsed;
- _assert$4(user.uid === localId, auth, "user-mismatch" /* AuthErrorCode.USER_MISMATCH */);
- return UserCredentialImpl._forOperation(user, operationType, response);
- }
- catch (e) {
- // Convert user deleted error into user mismatch
- if ((e === null || e === void 0 ? void 0 : e.code) === `auth/${"user-not-found" /* AuthErrorCode.USER_DELETED */}`) {
- _fail(auth, "user-mismatch" /* AuthErrorCode.USER_MISMATCH */);
- }
- throw e;
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function _signInWithCredential(auth, credential, bypassAuthState = false) {
- const operationType = "signIn" /* OperationType.SIGN_IN */;
- const response = await _processCredentialSavingMfaContextIfNecessary(auth, operationType, credential);
- const userCredential = await UserCredentialImpl._fromIdTokenResponse(auth, operationType, response);
- if (!bypassAuthState) {
- await auth._updateCurrentUser(userCredential.user);
- }
- return userCredential;
- }
- /**
- * Asynchronously signs in with the given credentials.
- *
- * @remarks
- * An {@link AuthProvider} can be used to generate the credential.
- *
- * @param auth - The {@link Auth} instance.
- * @param credential - The auth credential.
- *
- * @public
- */
- async function signInWithCredential(auth, credential) {
- return _signInWithCredential(_castAuth(auth), credential);
- }
- /**
- * Links the user account with the given credentials.
- *
- * @remarks
- * An {@link AuthProvider} can be used to generate the credential.
- *
- * @param user - The user.
- * @param credential - The auth credential.
- *
- * @public
- */
- async function linkWithCredential(user, credential) {
- const userInternal = getModularInstance(user);
- await _assertLinkedStatus(false, userInternal, credential.providerId);
- return _link$1(userInternal, credential);
- }
- /**
- * Re-authenticates a user using a fresh credential.
- *
- * @remarks
- * Use before operations such as {@link updatePassword} that require tokens from recent sign-in
- * attempts. This method can be used to recover from a `CREDENTIAL_TOO_OLD_LOGIN_AGAIN` error
- * or a `TOKEN_EXPIRED` error.
- *
- * @param user - The user.
- * @param credential - The auth credential.
- *
- * @public
- */
- async function reauthenticateWithCredential(user, credential) {
- return _reauthenticate(getModularInstance(user), credential);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function signInWithCustomToken$1(auth, request) {
- return _performSignInRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:signInWithCustomToken" /* Endpoint.SIGN_IN_WITH_CUSTOM_TOKEN */, _addTidIfNecessary(auth, request));
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Asynchronously signs in using a custom token.
- *
- * @remarks
- * Custom tokens are used to integrate Firebase Auth with existing auth systems, and must
- * be generated by an auth backend using the
- * {@link https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#createcustomtoken | createCustomToken}
- * method in the {@link https://firebase.google.com/docs/auth/admin | Admin SDK} .
- *
- * Fails with an error if the token is invalid, expired, or not accepted by the Firebase Auth service.
- *
- * @param auth - The {@link Auth} instance.
- * @param customToken - The custom token to sign in with.
- *
- * @public
- */
- async function signInWithCustomToken(auth, customToken) {
- const authInternal = _castAuth(auth);
- const response = await signInWithCustomToken$1(authInternal, {
- token: customToken,
- returnSecureToken: true
- });
- const cred = await UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn" /* OperationType.SIGN_IN */, response);
- await authInternal._updateCurrentUser(cred.user);
- return cred;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class MultiFactorInfoImpl {
- constructor(factorId, response) {
- this.factorId = factorId;
- this.uid = response.mfaEnrollmentId;
- this.enrollmentTime = new Date(response.enrolledAt).toUTCString();
- this.displayName = response.displayName;
- }
- static _fromServerResponse(auth, enrollment) {
- if ('phoneInfo' in enrollment) {
- return PhoneMultiFactorInfoImpl._fromServerResponse(auth, enrollment);
- }
- else if ('totpInfo' in enrollment) {
- return TotpMultiFactorInfoImpl._fromServerResponse(auth, enrollment);
- }
- return _fail(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- }
- class PhoneMultiFactorInfoImpl extends MultiFactorInfoImpl {
- constructor(response) {
- super("phone" /* FactorId.PHONE */, response);
- this.phoneNumber = response.phoneInfo;
- }
- static _fromServerResponse(_auth, enrollment) {
- return new PhoneMultiFactorInfoImpl(enrollment);
- }
- }
- class TotpMultiFactorInfoImpl extends MultiFactorInfoImpl {
- constructor(response) {
- super("totp" /* FactorId.TOTP */, response);
- }
- static _fromServerResponse(_auth, enrollment) {
- return new TotpMultiFactorInfoImpl(enrollment);
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _setActionCodeSettingsOnRequest(auth, request, actionCodeSettings) {
- var _a;
- _assert$4(((_a = actionCodeSettings.url) === null || _a === void 0 ? void 0 : _a.length) > 0, auth, "invalid-continue-uri" /* AuthErrorCode.INVALID_CONTINUE_URI */);
- _assert$4(typeof actionCodeSettings.dynamicLinkDomain === 'undefined' ||
- actionCodeSettings.dynamicLinkDomain.length > 0, auth, "invalid-dynamic-link-domain" /* AuthErrorCode.INVALID_DYNAMIC_LINK_DOMAIN */);
- request.continueUrl = actionCodeSettings.url;
- request.dynamicLinkDomain = actionCodeSettings.dynamicLinkDomain;
- request.canHandleCodeInApp = actionCodeSettings.handleCodeInApp;
- if (actionCodeSettings.iOS) {
- _assert$4(actionCodeSettings.iOS.bundleId.length > 0, auth, "missing-ios-bundle-id" /* AuthErrorCode.MISSING_IOS_BUNDLE_ID */);
- request.iOSBundleId = actionCodeSettings.iOS.bundleId;
- }
- if (actionCodeSettings.android) {
- _assert$4(actionCodeSettings.android.packageName.length > 0, auth, "missing-android-pkg-name" /* AuthErrorCode.MISSING_ANDROID_PACKAGE_NAME */);
- request.androidInstallApp = actionCodeSettings.android.installApp;
- request.androidMinimumVersionCode =
- actionCodeSettings.android.minimumVersion;
- request.androidPackageName = actionCodeSettings.android.packageName;
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Sends a password reset email to the given email address.
- *
- * @remarks
- * To complete the password reset, call {@link confirmPasswordReset} with the code supplied in
- * the email sent to the user, along with the new password specified by the user.
- *
- * @example
- * ```javascript
- * const actionCodeSettings = {
- * url: 'https://www.example.com/?email=user@example.com',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true
- * };
- * await sendPasswordResetEmail(auth, 'user@example.com', actionCodeSettings);
- * // Obtain code from user.
- * await confirmPasswordReset('user@example.com', code);
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param email - The user's email address.
- * @param actionCodeSettings - The {@link ActionCodeSettings}.
- *
- * @public
- */
- async function sendPasswordResetEmail(auth, email, actionCodeSettings) {
- var _a;
- const authInternal = _castAuth(auth);
- const request = {
- requestType: "PASSWORD_RESET" /* ActionCodeOperation.PASSWORD_RESET */,
- email,
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */
- };
- if ((_a = authInternal._getRecaptchaConfig()) === null || _a === void 0 ? void 0 : _a.emailPasswordEnabled) {
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */, true);
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(authInternal, requestWithRecaptcha, actionCodeSettings);
- }
- await sendPasswordResetEmail$1(authInternal, requestWithRecaptcha);
- }
- else {
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(authInternal, request, actionCodeSettings);
- }
- await sendPasswordResetEmail$1(authInternal, request)
- .catch(async (error) => {
- if (error.code === `auth/${"missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */}`) {
- console.log('Password resets are protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the password reset flow.');
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */, true);
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(authInternal, requestWithRecaptcha, actionCodeSettings);
- }
- await sendPasswordResetEmail$1(authInternal, requestWithRecaptcha);
- }
- else {
- return Promise.reject(error);
- }
- });
- }
- }
- /**
- * Completes the password reset process, given a confirmation code and new password.
- *
- * @param auth - The {@link Auth} instance.
- * @param oobCode - A confirmation code sent to the user.
- * @param newPassword - The new password.
- *
- * @public
- */
- async function confirmPasswordReset(auth, oobCode, newPassword) {
- await resetPassword(getModularInstance(auth), {
- oobCode,
- newPassword
- });
- // Do not return the email.
- }
- /**
- * Applies a verification code sent to the user by email or other out-of-band mechanism.
- *
- * @param auth - The {@link Auth} instance.
- * @param oobCode - A verification code sent to the user.
- *
- * @public
- */
- async function applyActionCode(auth, oobCode) {
- await applyActionCode$1(getModularInstance(auth), { oobCode });
- }
- /**
- * Checks a verification code sent to the user by email or other out-of-band mechanism.
- *
- * @returns metadata about the code.
- *
- * @param auth - The {@link Auth} instance.
- * @param oobCode - A verification code sent to the user.
- *
- * @public
- */
- async function checkActionCode(auth, oobCode) {
- const authModular = getModularInstance(auth);
- const response = await resetPassword(authModular, { oobCode });
- // Email could be empty only if the request type is EMAIL_SIGNIN or
- // VERIFY_AND_CHANGE_EMAIL.
- // New email should not be empty if the request type is
- // VERIFY_AND_CHANGE_EMAIL.
- // Multi-factor info could not be empty if the request type is
- // REVERT_SECOND_FACTOR_ADDITION.
- const operation = response.requestType;
- _assert$4(operation, authModular, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- switch (operation) {
- case "EMAIL_SIGNIN" /* ActionCodeOperation.EMAIL_SIGNIN */:
- break;
- case "VERIFY_AND_CHANGE_EMAIL" /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */:
- _assert$4(response.newEmail, authModular, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- break;
- case "REVERT_SECOND_FACTOR_ADDITION" /* ActionCodeOperation.REVERT_SECOND_FACTOR_ADDITION */:
- _assert$4(response.mfaInfo, authModular, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- // fall through
- default:
- _assert$4(response.email, authModular, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- // The multi-factor info for revert second factor addition
- let multiFactorInfo = null;
- if (response.mfaInfo) {
- multiFactorInfo = MultiFactorInfoImpl._fromServerResponse(_castAuth(authModular), response.mfaInfo);
- }
- return {
- data: {
- email: (response.requestType === "VERIFY_AND_CHANGE_EMAIL" /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */
- ? response.newEmail
- : response.email) || null,
- previousEmail: (response.requestType === "VERIFY_AND_CHANGE_EMAIL" /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */
- ? response.email
- : response.newEmail) || null,
- multiFactorInfo
- },
- operation
- };
- }
- /**
- * Checks a password reset code sent to the user by email or other out-of-band mechanism.
- *
- * @returns the user's email address if valid.
- *
- * @param auth - The {@link Auth} instance.
- * @param code - A verification code sent to the user.
- *
- * @public
- */
- async function verifyPasswordResetCode(auth, code) {
- const { data } = await checkActionCode(getModularInstance(auth), code);
- // Email should always be present since a code was sent to it
- return data.email;
- }
- /**
- * Creates a new user account associated with the specified email address and password.
- *
- * @remarks
- * On successful creation of the user account, this user will also be signed in to your application.
- *
- * User account creation can fail if the account already exists or the password is invalid.
- *
- * Note: The email address acts as a unique identifier for the user and enables an email-based
- * password reset. This function will create a new user account and set the initial user password.
- *
- * @param auth - The {@link Auth} instance.
- * @param email - The user's email address.
- * @param password - The user's chosen password.
- *
- * @public
- */
- async function createUserWithEmailAndPassword(auth, email, password) {
- var _a;
- const authInternal = _castAuth(auth);
- const request = {
- returnSecureToken: true,
- email,
- password,
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */
- };
- let signUpResponse;
- if ((_a = authInternal._getRecaptchaConfig()) === null || _a === void 0 ? void 0 : _a.emailPasswordEnabled) {
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "signUpPassword" /* RecaptchaActionName.SIGN_UP_PASSWORD */);
- signUpResponse = signUp(authInternal, requestWithRecaptcha);
- }
- else {
- signUpResponse = signUp(authInternal, request).catch(async (error) => {
- if (error.code === `auth/${"missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */}`) {
- console.log('Sign-up is protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the sign-up flow.');
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "signUpPassword" /* RecaptchaActionName.SIGN_UP_PASSWORD */);
- return signUp(authInternal, requestWithRecaptcha);
- }
- else {
- return Promise.reject(error);
- }
- });
- }
- const response = await signUpResponse.catch(error => {
- return Promise.reject(error);
- });
- const userCredential = await UserCredentialImpl._fromIdTokenResponse(authInternal, "signIn" /* OperationType.SIGN_IN */, response);
- await authInternal._updateCurrentUser(userCredential.user);
- return userCredential;
- }
- /**
- * Asynchronously signs in using an email and password.
- *
- * @remarks
- * Fails with an error if the email address and password do not match.
- *
- * Note: The user's password is NOT the password used to access the user's email account. The
- * email address serves as a unique identifier for the user, and the password is used to access
- * the user's account in your Firebase project. See also: {@link createUserWithEmailAndPassword}.
- *
- * @param auth - The {@link Auth} instance.
- * @param email - The users email address.
- * @param password - The users password.
- *
- * @public
- */
- function signInWithEmailAndPassword(auth, email, password) {
- return signInWithCredential(getModularInstance(auth), EmailAuthProvider.credential(email, password));
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Sends a sign-in email link to the user with the specified email.
- *
- * @remarks
- * The sign-in operation has to always be completed in the app unlike other out of band email
- * actions (password reset and email verifications). This is because, at the end of the flow,
- * the user is expected to be signed in and their Auth state persisted within the app.
- *
- * To complete sign in with the email link, call {@link signInWithEmailLink} with the email
- * address and the email link supplied in the email sent to the user.
- *
- * @example
- * ```javascript
- * const actionCodeSettings = {
- * url: 'https://www.example.com/?email=user@example.com',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true
- * };
- * await sendSignInLinkToEmail(auth, 'user@example.com', actionCodeSettings);
- * // Obtain emailLink from the user.
- * if(isSignInWithEmailLink(auth, emailLink)) {
- * await signInWithEmailLink(auth, 'user@example.com', emailLink);
- * }
- * ```
- *
- * @param authInternal - The {@link Auth} instance.
- * @param email - The user's email address.
- * @param actionCodeSettings - The {@link ActionCodeSettings}.
- *
- * @public
- */
- async function sendSignInLinkToEmail(auth, email, actionCodeSettings) {
- var _a;
- const authInternal = _castAuth(auth);
- const request = {
- requestType: "EMAIL_SIGNIN" /* ActionCodeOperation.EMAIL_SIGNIN */,
- email,
- clientType: "CLIENT_TYPE_WEB" /* RecaptchaClientType.WEB */
- };
- function setActionCodeSettings(request, actionCodeSettings) {
- _assert$4(actionCodeSettings.handleCodeInApp, authInternal, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(authInternal, request, actionCodeSettings);
- }
- }
- if ((_a = authInternal._getRecaptchaConfig()) === null || _a === void 0 ? void 0 : _a.emailPasswordEnabled) {
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */, true);
- setActionCodeSettings(requestWithRecaptcha, actionCodeSettings);
- await sendSignInLinkToEmail$1(authInternal, requestWithRecaptcha);
- }
- else {
- setActionCodeSettings(request, actionCodeSettings);
- await sendSignInLinkToEmail$1(authInternal, request)
- .catch(async (error) => {
- if (error.code === `auth/${"missing-recaptcha-token" /* AuthErrorCode.MISSING_RECAPTCHA_TOKEN */}`) {
- console.log('Email link sign-in is protected by reCAPTCHA for this project. Automatically triggering the reCAPTCHA flow and restarting the sign-in flow.');
- const requestWithRecaptcha = await injectRecaptchaFields(authInternal, request, "getOobCode" /* RecaptchaActionName.GET_OOB_CODE */, true);
- setActionCodeSettings(requestWithRecaptcha, actionCodeSettings);
- await sendSignInLinkToEmail$1(authInternal, requestWithRecaptcha);
- }
- else {
- return Promise.reject(error);
- }
- });
- }
- }
- /**
- * Checks if an incoming link is a sign-in with email link suitable for {@link signInWithEmailLink}.
- *
- * @param auth - The {@link Auth} instance.
- * @param emailLink - The link sent to the user's email address.
- *
- * @public
- */
- function isSignInWithEmailLink(auth, emailLink) {
- const actionCodeUrl = ActionCodeURL.parseLink(emailLink);
- return (actionCodeUrl === null || actionCodeUrl === void 0 ? void 0 : actionCodeUrl.operation) === "EMAIL_SIGNIN" /* ActionCodeOperation.EMAIL_SIGNIN */;
- }
- /**
- * Asynchronously signs in using an email and sign-in email link.
- *
- * @remarks
- * If no link is passed, the link is inferred from the current URL.
- *
- * Fails with an error if the email address is invalid or OTP in email link expires.
- *
- * Note: Confirm the link is a sign-in email link before calling this method firebase.auth.Auth.isSignInWithEmailLink.
- *
- * @example
- * ```javascript
- * const actionCodeSettings = {
- * url: 'https://www.example.com/?email=user@example.com',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true
- * };
- * await sendSignInLinkToEmail(auth, 'user@example.com', actionCodeSettings);
- * // Obtain emailLink from the user.
- * if(isSignInWithEmailLink(auth, emailLink)) {
- * await signInWithEmailLink(auth, 'user@example.com', emailLink);
- * }
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param email - The user's email address.
- * @param emailLink - The link sent to the user's email address.
- *
- * @public
- */
- async function signInWithEmailLink(auth, email, emailLink) {
- const authModular = getModularInstance(auth);
- const credential = EmailAuthProvider.credentialWithLink(email, emailLink || _getCurrentUrl());
- // Check if the tenant ID in the email link matches the tenant ID on Auth
- // instance.
- _assert$4(credential._tenantId === (authModular.tenantId || null), authModular, "tenant-id-mismatch" /* AuthErrorCode.TENANT_ID_MISMATCH */);
- return signInWithCredential(authModular, credential);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function createAuthUri(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:createAuthUri" /* Endpoint.CREATE_AUTH_URI */, _addTidIfNecessary(auth, request));
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Gets the list of possible sign in methods for the given email address.
- *
- * @remarks
- * This is useful to differentiate methods of sign-in for the same provider, eg.
- * {@link EmailAuthProvider} which has 2 methods of sign-in,
- * {@link SignInMethod}.EMAIL_PASSWORD and
- * {@link SignInMethod}.EMAIL_LINK.
- *
- * @param auth - The {@link Auth} instance.
- * @param email - The user's email address.
- *
- * @public
- */
- async function fetchSignInMethodsForEmail(auth, email) {
- // createAuthUri returns an error if continue URI is not http or https.
- // For environments like Cordova, Chrome extensions, native frameworks, file
- // systems, etc, use http://localhost as continue URL.
- const continueUri = _isHttpOrHttps$1() ? _getCurrentUrl() : 'http://localhost';
- const request = {
- identifier: email,
- continueUri
- };
- const { signinMethods } = await createAuthUri(getModularInstance(auth), request);
- return signinMethods || [];
- }
- /**
- * Sends a verification email to a user.
- *
- * @remarks
- * The verification process is completed by calling {@link applyActionCode}.
- *
- * @example
- * ```javascript
- * const actionCodeSettings = {
- * url: 'https://www.example.com/?email=user@example.com',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true
- * };
- * await sendEmailVerification(user, actionCodeSettings);
- * // Obtain code from the user.
- * await applyActionCode(auth, code);
- * ```
- *
- * @param user - The user.
- * @param actionCodeSettings - The {@link ActionCodeSettings}.
- *
- * @public
- */
- async function sendEmailVerification(user, actionCodeSettings) {
- const userInternal = getModularInstance(user);
- const idToken = await user.getIdToken();
- const request = {
- requestType: "VERIFY_EMAIL" /* ActionCodeOperation.VERIFY_EMAIL */,
- idToken
- };
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(userInternal.auth, request, actionCodeSettings);
- }
- const { email } = await sendEmailVerification$1(userInternal.auth, request);
- if (email !== user.email) {
- await user.reload();
- }
- }
- /**
- * Sends a verification email to a new email address.
- *
- * @remarks
- * The user's email will be updated to the new one after being verified.
- *
- * If you have a custom email action handler, you can complete the verification process by calling
- * {@link applyActionCode}.
- *
- * @example
- * ```javascript
- * const actionCodeSettings = {
- * url: 'https://www.example.com/?email=user@example.com',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true
- * };
- * await verifyBeforeUpdateEmail(user, 'newemail@example.com', actionCodeSettings);
- * // Obtain code from the user.
- * await applyActionCode(auth, code);
- * ```
- *
- * @param user - The user.
- * @param newEmail - The new email address to be verified before update.
- * @param actionCodeSettings - The {@link ActionCodeSettings}.
- *
- * @public
- */
- async function verifyBeforeUpdateEmail(user, newEmail, actionCodeSettings) {
- const userInternal = getModularInstance(user);
- const idToken = await user.getIdToken();
- const request = {
- requestType: "VERIFY_AND_CHANGE_EMAIL" /* ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL */,
- idToken,
- newEmail
- };
- if (actionCodeSettings) {
- _setActionCodeSettingsOnRequest(userInternal.auth, request, actionCodeSettings);
- }
- const { email } = await verifyAndChangeEmail(userInternal.auth, request);
- if (email !== user.email) {
- // If the local copy of the email on user is outdated, reload the
- // user.
- await user.reload();
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function updateProfile$1(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v1/accounts:update" /* Endpoint.SET_ACCOUNT_INFO */, request);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Updates a user's profile data.
- *
- * @param user - The user.
- * @param profile - The profile's `displayName` and `photoURL` to update.
- *
- * @public
- */
- async function updateProfile(user, { displayName, photoURL: photoUrl }) {
- if (displayName === undefined && photoUrl === undefined) {
- return;
- }
- const userInternal = getModularInstance(user);
- const idToken = await userInternal.getIdToken();
- const profileRequest = {
- idToken,
- displayName,
- photoUrl,
- returnSecureToken: true
- };
- const response = await _logoutIfInvalidated(userInternal, updateProfile$1(userInternal.auth, profileRequest));
- userInternal.displayName = response.displayName || null;
- userInternal.photoURL = response.photoUrl || null;
- // Update the password provider as well
- const passwordProvider = userInternal.providerData.find(({ providerId }) => providerId === "password" /* ProviderId.PASSWORD */);
- if (passwordProvider) {
- passwordProvider.displayName = userInternal.displayName;
- passwordProvider.photoURL = userInternal.photoURL;
- }
- await userInternal._updateTokensIfNecessary(response);
- }
- /**
- * Updates the user's email address.
- *
- * @remarks
- * An email will be sent to the original email address (if it was set) that allows to revoke the
- * email address change, in order to protect them from account hijacking.
- *
- * Important: this is a security sensitive operation that requires the user to have recently signed
- * in. If this requirement isn't met, ask the user to authenticate again and then call
- * {@link reauthenticateWithCredential}.
- *
- * @param user - The user.
- * @param newEmail - The new email address.
- *
- * @public
- */
- function updateEmail(user, newEmail) {
- return updateEmailOrPassword(getModularInstance(user), newEmail, null);
- }
- /**
- * Updates the user's password.
- *
- * @remarks
- * Important: this is a security sensitive operation that requires the user to have recently signed
- * in. If this requirement isn't met, ask the user to authenticate again and then call
- * {@link reauthenticateWithCredential}.
- *
- * @param user - The user.
- * @param newPassword - The new password.
- *
- * @public
- */
- function updatePassword(user, newPassword) {
- return updateEmailOrPassword(getModularInstance(user), null, newPassword);
- }
- async function updateEmailOrPassword(user, email, password) {
- const { auth } = user;
- const idToken = await user.getIdToken();
- const request = {
- idToken,
- returnSecureToken: true
- };
- if (email) {
- request.email = email;
- }
- if (password) {
- request.password = password;
- }
- const response = await _logoutIfInvalidated(user, updateEmailPassword(auth, request));
- await user._updateTokensIfNecessary(response, /* reload */ true);
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Parse the `AdditionalUserInfo` from the ID token response.
- *
- */
- function _fromIdTokenResponse(idTokenResponse) {
- var _a, _b;
- if (!idTokenResponse) {
- return null;
- }
- const { providerId } = idTokenResponse;
- const profile = idTokenResponse.rawUserInfo
- ? JSON.parse(idTokenResponse.rawUserInfo)
- : {};
- const isNewUser = idTokenResponse.isNewUser ||
- idTokenResponse.kind === "identitytoolkit#SignupNewUserResponse" /* IdTokenResponseKind.SignupNewUser */;
- if (!providerId && (idTokenResponse === null || idTokenResponse === void 0 ? void 0 : idTokenResponse.idToken)) {
- const signInProvider = (_b = (_a = _parseToken(idTokenResponse.idToken)) === null || _a === void 0 ? void 0 : _a.firebase) === null || _b === void 0 ? void 0 : _b['sign_in_provider'];
- if (signInProvider) {
- const filteredProviderId = signInProvider !== "anonymous" /* ProviderId.ANONYMOUS */ &&
- signInProvider !== "custom" /* ProviderId.CUSTOM */
- ? signInProvider
- : null;
- // Uses generic class in accordance with the legacy SDK.
- return new GenericAdditionalUserInfo(isNewUser, filteredProviderId);
- }
- }
- if (!providerId) {
- return null;
- }
- switch (providerId) {
- case "facebook.com" /* ProviderId.FACEBOOK */:
- return new FacebookAdditionalUserInfo(isNewUser, profile);
- case "github.com" /* ProviderId.GITHUB */:
- return new GithubAdditionalUserInfo(isNewUser, profile);
- case "google.com" /* ProviderId.GOOGLE */:
- return new GoogleAdditionalUserInfo(isNewUser, profile);
- case "twitter.com" /* ProviderId.TWITTER */:
- return new TwitterAdditionalUserInfo(isNewUser, profile, idTokenResponse.screenName || null);
- case "custom" /* ProviderId.CUSTOM */:
- case "anonymous" /* ProviderId.ANONYMOUS */:
- return new GenericAdditionalUserInfo(isNewUser, null);
- default:
- return new GenericAdditionalUserInfo(isNewUser, providerId, profile);
- }
- }
- class GenericAdditionalUserInfo {
- constructor(isNewUser, providerId, profile = {}) {
- this.isNewUser = isNewUser;
- this.providerId = providerId;
- this.profile = profile;
- }
- }
- class FederatedAdditionalUserInfoWithUsername extends GenericAdditionalUserInfo {
- constructor(isNewUser, providerId, profile, username) {
- super(isNewUser, providerId, profile);
- this.username = username;
- }
- }
- class FacebookAdditionalUserInfo extends GenericAdditionalUserInfo {
- constructor(isNewUser, profile) {
- super(isNewUser, "facebook.com" /* ProviderId.FACEBOOK */, profile);
- }
- }
- class GithubAdditionalUserInfo extends FederatedAdditionalUserInfoWithUsername {
- constructor(isNewUser, profile) {
- super(isNewUser, "github.com" /* ProviderId.GITHUB */, profile, typeof (profile === null || profile === void 0 ? void 0 : profile.login) === 'string' ? profile === null || profile === void 0 ? void 0 : profile.login : null);
- }
- }
- class GoogleAdditionalUserInfo extends GenericAdditionalUserInfo {
- constructor(isNewUser, profile) {
- super(isNewUser, "google.com" /* ProviderId.GOOGLE */, profile);
- }
- }
- class TwitterAdditionalUserInfo extends FederatedAdditionalUserInfoWithUsername {
- constructor(isNewUser, profile, screenName) {
- super(isNewUser, "twitter.com" /* ProviderId.TWITTER */, profile, screenName);
- }
- }
- /**
- * Extracts provider specific {@link AdditionalUserInfo} for the given credential.
- *
- * @param userCredential - The user credential.
- *
- * @public
- */
- function getAdditionalUserInfo(userCredential) {
- const { user, _tokenResponse } = userCredential;
- if (user.isAnonymous && !_tokenResponse) {
- // Handle the special case where signInAnonymously() gets called twice.
- // No network call is made so there's nothing to actually fill this in
- return {
- providerId: null,
- isNewUser: false,
- profile: null
- };
- }
- return _fromIdTokenResponse(_tokenResponse);
- }
-
- class MultiFactorSessionImpl {
- constructor(type, credential, auth) {
- this.type = type;
- this.credential = credential;
- this.auth = auth;
- }
- static _fromIdtoken(idToken, auth) {
- return new MultiFactorSessionImpl("enroll" /* MultiFactorSessionType.ENROLL */, idToken, auth);
- }
- static _fromMfaPendingCredential(mfaPendingCredential) {
- return new MultiFactorSessionImpl("signin" /* MultiFactorSessionType.SIGN_IN */, mfaPendingCredential);
- }
- toJSON() {
- const key = this.type === "enroll" /* MultiFactorSessionType.ENROLL */
- ? 'idToken'
- : 'pendingCredential';
- return {
- multiFactorSession: {
- [key]: this.credential
- }
- };
- }
- static fromJSON(obj) {
- var _a, _b;
- if (obj === null || obj === void 0 ? void 0 : obj.multiFactorSession) {
- if ((_a = obj.multiFactorSession) === null || _a === void 0 ? void 0 : _a.pendingCredential) {
- return MultiFactorSessionImpl._fromMfaPendingCredential(obj.multiFactorSession.pendingCredential);
- }
- else if ((_b = obj.multiFactorSession) === null || _b === void 0 ? void 0 : _b.idToken) {
- return MultiFactorSessionImpl._fromIdtoken(obj.multiFactorSession.idToken);
- }
- }
- return null;
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class MultiFactorResolverImpl {
- constructor(session, hints, signInResolver) {
- this.session = session;
- this.hints = hints;
- this.signInResolver = signInResolver;
- }
- /** @internal */
- static _fromError(authExtern, error) {
- const auth = _castAuth(authExtern);
- const serverResponse = error.customData._serverResponse;
- const hints = (serverResponse.mfaInfo || []).map(enrollment => MultiFactorInfoImpl._fromServerResponse(auth, enrollment));
- _assert$4(serverResponse.mfaPendingCredential, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const session = MultiFactorSessionImpl._fromMfaPendingCredential(serverResponse.mfaPendingCredential);
- return new MultiFactorResolverImpl(session, hints, async (assertion) => {
- const mfaResponse = await assertion._process(auth, session);
- // Clear out the unneeded fields from the old login response
- delete serverResponse.mfaInfo;
- delete serverResponse.mfaPendingCredential;
- // Use in the new token & refresh token in the old response
- const idTokenResponse = Object.assign(Object.assign({}, serverResponse), { idToken: mfaResponse.idToken, refreshToken: mfaResponse.refreshToken });
- // TODO: we should collapse this switch statement into UserCredentialImpl._forOperation and have it support the SIGN_IN case
- switch (error.operationType) {
- case "signIn" /* OperationType.SIGN_IN */:
- const userCredential = await UserCredentialImpl._fromIdTokenResponse(auth, error.operationType, idTokenResponse);
- await auth._updateCurrentUser(userCredential.user);
- return userCredential;
- case "reauthenticate" /* OperationType.REAUTHENTICATE */:
- _assert$4(error.user, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return UserCredentialImpl._forOperation(error.user, error.operationType, idTokenResponse);
- default:
- _fail(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- });
- }
- async resolveSignIn(assertionExtern) {
- const assertion = assertionExtern;
- return this.signInResolver(assertion);
- }
- }
- /**
- * Provides a {@link MultiFactorResolver} suitable for completion of a
- * multi-factor flow.
- *
- * @param auth - The {@link Auth} instance.
- * @param error - The {@link MultiFactorError} raised during a sign-in, or
- * reauthentication operation.
- *
- * @public
- */
- function getMultiFactorResolver(auth, error) {
- var _a;
- const authModular = getModularInstance(auth);
- const errorInternal = error;
- _assert$4(error.customData.operationType, authModular, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- _assert$4((_a = errorInternal.customData._serverResponse) === null || _a === void 0 ? void 0 : _a.mfaPendingCredential, authModular, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- return MultiFactorResolverImpl._fromError(authModular, errorInternal);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function startEnrollPhoneMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaEnrollment:start" /* Endpoint.START_MFA_ENROLLMENT */, _addTidIfNecessary(auth, request));
- }
- function finalizeEnrollPhoneMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaEnrollment:finalize" /* Endpoint.FINALIZE_MFA_ENROLLMENT */, _addTidIfNecessary(auth, request));
- }
- function withdrawMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaEnrollment:withdraw" /* Endpoint.WITHDRAW_MFA */, _addTidIfNecessary(auth, request));
- }
-
- class MultiFactorUserImpl {
- constructor(user) {
- this.user = user;
- this.enrolledFactors = [];
- user._onReload(userInfo => {
- if (userInfo.mfaInfo) {
- this.enrolledFactors = userInfo.mfaInfo.map(enrollment => MultiFactorInfoImpl._fromServerResponse(user.auth, enrollment));
- }
- });
- }
- static _fromUser(user) {
- return new MultiFactorUserImpl(user);
- }
- async getSession() {
- return MultiFactorSessionImpl._fromIdtoken(await this.user.getIdToken(), this.user.auth);
- }
- async enroll(assertionExtern, displayName) {
- const assertion = assertionExtern;
- const session = (await this.getSession());
- const finalizeMfaResponse = await _logoutIfInvalidated(this.user, assertion._process(this.user.auth, session, displayName));
- // New tokens will be issued after enrollment of the new second factors.
- // They need to be updated on the user.
- await this.user._updateTokensIfNecessary(finalizeMfaResponse);
- // The user needs to be reloaded to get the new multi-factor information
- // from server. USER_RELOADED event will be triggered and `enrolledFactors`
- // will be updated.
- return this.user.reload();
- }
- async unenroll(infoOrUid) {
- const mfaEnrollmentId = typeof infoOrUid === 'string' ? infoOrUid : infoOrUid.uid;
- const idToken = await this.user.getIdToken();
- try {
- const idTokenResponse = await _logoutIfInvalidated(this.user, withdrawMfa(this.user.auth, {
- idToken,
- mfaEnrollmentId
- }));
- // Remove the second factor from the user's list.
- this.enrolledFactors = this.enrolledFactors.filter(({ uid }) => uid !== mfaEnrollmentId);
- // Depending on whether the backend decided to revoke the user's session,
- // the tokenResponse may be empty. If the tokens were not updated (and they
- // are now invalid), reloading the user will discover this and invalidate
- // the user's state accordingly.
- await this.user._updateTokensIfNecessary(idTokenResponse);
- await this.user.reload();
- }
- catch (e) {
- throw e;
- }
- }
- }
- const multiFactorUserCache = new WeakMap();
- /**
- * The {@link MultiFactorUser} corresponding to the user.
- *
- * @remarks
- * This is used to access all multi-factor properties and operations related to the user.
- *
- * @param user - The user.
- *
- * @public
- */
- function multiFactor(user) {
- const userModular = getModularInstance(user);
- if (!multiFactorUserCache.has(userModular)) {
- multiFactorUserCache.set(userModular, MultiFactorUserImpl._fromUser(userModular));
- }
- return multiFactorUserCache.get(userModular);
- }
-
- const STORAGE_AVAILABLE_KEY = '__sak';
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // There are two different browser persistence types: local and session.
- // Both have the same implementation but use a different underlying storage
- // object.
- class BrowserPersistenceClass {
- constructor(storageRetriever, type) {
- this.storageRetriever = storageRetriever;
- this.type = type;
- }
- _isAvailable() {
- try {
- if (!this.storage) {
- return Promise.resolve(false);
- }
- this.storage.setItem(STORAGE_AVAILABLE_KEY, '1');
- this.storage.removeItem(STORAGE_AVAILABLE_KEY);
- return Promise.resolve(true);
- }
- catch (_a) {
- return Promise.resolve(false);
- }
- }
- _set(key, value) {
- this.storage.setItem(key, JSON.stringify(value));
- return Promise.resolve();
- }
- _get(key) {
- const json = this.storage.getItem(key);
- return Promise.resolve(json ? JSON.parse(json) : null);
- }
- _remove(key) {
- this.storage.removeItem(key);
- return Promise.resolve();
- }
- get storage() {
- return this.storageRetriever();
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _iframeCannotSyncWebStorage() {
- const ua = getUA();
- return _isSafari(ua) || _isIOS(ua);
- }
- // The polling period in case events are not supported
- const _POLLING_INTERVAL_MS$1 = 1000;
- // The IE 10 localStorage cross tab synchronization delay in milliseconds
- const IE10_LOCAL_STORAGE_SYNC_DELAY = 10;
- class BrowserLocalPersistence extends BrowserPersistenceClass {
- constructor() {
- super(() => window.localStorage, "LOCAL" /* PersistenceType.LOCAL */);
- this.boundEventHandler = (event, poll) => this.onStorageEvent(event, poll);
- this.listeners = {};
- this.localCache = {};
- // setTimeout return value is platform specific
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- this.pollTimer = null;
- // Safari or iOS browser and embedded in an iframe.
- this.safariLocalStorageNotSynced = _iframeCannotSyncWebStorage() && _isIframe();
- // Whether to use polling instead of depending on window events
- this.fallbackToPolling = _isMobileBrowser();
- this._shouldAllowMigration = true;
- }
- forAllChangedKeys(cb) {
- // Check all keys with listeners on them.
- for (const key of Object.keys(this.listeners)) {
- // Get value from localStorage.
- const newValue = this.storage.getItem(key);
- const oldValue = this.localCache[key];
- // If local map value does not match, trigger listener with storage event.
- // Differentiate this simulated event from the real storage event.
- if (newValue !== oldValue) {
- cb(key, oldValue, newValue);
- }
- }
- }
- onStorageEvent(event, poll = false) {
- // Key would be null in some situations, like when localStorage is cleared
- if (!event.key) {
- this.forAllChangedKeys((key, _oldValue, newValue) => {
- this.notifyListeners(key, newValue);
- });
- return;
- }
- const key = event.key;
- // Check the mechanism how this event was detected.
- // The first event will dictate the mechanism to be used.
- if (poll) {
- // Environment detects storage changes via polling.
- // Remove storage event listener to prevent possible event duplication.
- this.detachListener();
- }
- else {
- // Environment detects storage changes via storage event listener.
- // Remove polling listener to prevent possible event duplication.
- this.stopPolling();
- }
- // Safari embedded iframe. Storage event will trigger with the delta
- // changes but no changes will be applied to the iframe localStorage.
- if (this.safariLocalStorageNotSynced) {
- // Get current iframe page value.
- const storedValue = this.storage.getItem(key);
- // Value not synchronized, synchronize manually.
- if (event.newValue !== storedValue) {
- if (event.newValue !== null) {
- // Value changed from current value.
- this.storage.setItem(key, event.newValue);
- }
- else {
- // Current value deleted.
- this.storage.removeItem(key);
- }
- }
- else if (this.localCache[key] === event.newValue && !poll) {
- // Already detected and processed, do not trigger listeners again.
- return;
- }
- }
- const triggerListeners = () => {
- // Keep local map up to date in case storage event is triggered before
- // poll.
- const storedValue = this.storage.getItem(key);
- if (!poll && this.localCache[key] === storedValue) {
- // Real storage event which has already been detected, do nothing.
- // This seems to trigger in some IE browsers for some reason.
- return;
- }
- this.notifyListeners(key, storedValue);
- };
- const storedValue = this.storage.getItem(key);
- if (_isIE10() &&
- storedValue !== event.newValue &&
- event.newValue !== event.oldValue) {
- // IE 10 has this weird bug where a storage event would trigger with the
- // correct key, oldValue and newValue but localStorage.getItem(key) does
- // not yield the updated value until a few milliseconds. This ensures
- // this recovers from that situation.
- setTimeout(triggerListeners, IE10_LOCAL_STORAGE_SYNC_DELAY);
- }
- else {
- triggerListeners();
- }
- }
- notifyListeners(key, value) {
- this.localCache[key] = value;
- const listeners = this.listeners[key];
- if (listeners) {
- for (const listener of Array.from(listeners)) {
- listener(value ? JSON.parse(value) : value);
- }
- }
- }
- startPolling() {
- this.stopPolling();
- this.pollTimer = setInterval(() => {
- this.forAllChangedKeys((key, oldValue, newValue) => {
- this.onStorageEvent(new StorageEvent('storage', {
- key,
- oldValue,
- newValue
- }),
- /* poll */ true);
- });
- }, _POLLING_INTERVAL_MS$1);
- }
- stopPolling() {
- if (this.pollTimer) {
- clearInterval(this.pollTimer);
- this.pollTimer = null;
- }
- }
- attachListener() {
- window.addEventListener('storage', this.boundEventHandler);
- }
- detachListener() {
- window.removeEventListener('storage', this.boundEventHandler);
- }
- _addListener(key, listener) {
- if (Object.keys(this.listeners).length === 0) {
- // Whether browser can detect storage event when it had already been pushed to the background.
- // This may happen in some mobile browsers. A localStorage change in the foreground window
- // will not be detected in the background window via the storage event.
- // This was detected in iOS 7.x mobile browsers
- if (this.fallbackToPolling) {
- this.startPolling();
- }
- else {
- this.attachListener();
- }
- }
- if (!this.listeners[key]) {
- this.listeners[key] = new Set();
- // Populate the cache to avoid spuriously triggering on first poll.
- this.localCache[key] = this.storage.getItem(key);
- }
- this.listeners[key].add(listener);
- }
- _removeListener(key, listener) {
- if (this.listeners[key]) {
- this.listeners[key].delete(listener);
- if (this.listeners[key].size === 0) {
- delete this.listeners[key];
- }
- }
- if (Object.keys(this.listeners).length === 0) {
- this.detachListener();
- this.stopPolling();
- }
- }
- // Update local cache on base operations:
- async _set(key, value) {
- await super._set(key, value);
- this.localCache[key] = JSON.stringify(value);
- }
- async _get(key) {
- const value = await super._get(key);
- this.localCache[key] = JSON.stringify(value);
- return value;
- }
- async _remove(key) {
- await super._remove(key);
- delete this.localCache[key];
- }
- }
- BrowserLocalPersistence.type = 'LOCAL';
- /**
- * An implementation of {@link Persistence} of type `LOCAL` using `localStorage`
- * for the underlying storage.
- *
- * @public
- */
- const browserLocalPersistence = BrowserLocalPersistence;
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class BrowserSessionPersistence extends BrowserPersistenceClass {
- constructor() {
- super(() => window.sessionStorage, "SESSION" /* PersistenceType.SESSION */);
- }
- _addListener(_key, _listener) {
- // Listeners are not supported for session storage since it cannot be shared across windows
- return;
- }
- _removeListener(_key, _listener) {
- // Listeners are not supported for session storage since it cannot be shared across windows
- return;
- }
- }
- BrowserSessionPersistence.type = 'SESSION';
- /**
- * An implementation of {@link Persistence} of `SESSION` using `sessionStorage`
- * for the underlying storage.
- *
- * @public
- */
- const browserSessionPersistence = BrowserSessionPersistence;
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Shim for Promise.allSettled, note the slightly different format of `fulfilled` vs `status`.
- *
- * @param promises - Array of promises to wait on.
- */
- function _allSettled(promises) {
- return Promise.all(promises.map(async (promise) => {
- try {
- const value = await promise;
- return {
- fulfilled: true,
- value
- };
- }
- catch (reason) {
- return {
- fulfilled: false,
- reason
- };
- }
- }));
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Interface class for receiving messages.
- *
- */
- class Receiver {
- constructor(eventTarget) {
- this.eventTarget = eventTarget;
- this.handlersMap = {};
- this.boundEventHandler = this.handleEvent.bind(this);
- }
- /**
- * Obtain an instance of a Receiver for a given event target, if none exists it will be created.
- *
- * @param eventTarget - An event target (such as window or self) through which the underlying
- * messages will be received.
- */
- static _getInstance(eventTarget) {
- // The results are stored in an array since objects can't be keys for other
- // objects. In addition, setting a unique property on an event target as a
- // hash map key may not be allowed due to CORS restrictions.
- const existingInstance = this.receivers.find(receiver => receiver.isListeningto(eventTarget));
- if (existingInstance) {
- return existingInstance;
- }
- const newInstance = new Receiver(eventTarget);
- this.receivers.push(newInstance);
- return newInstance;
- }
- isListeningto(eventTarget) {
- return this.eventTarget === eventTarget;
- }
- /**
- * Fans out a MessageEvent to the appropriate listeners.
- *
- * @remarks
- * Sends an {@link Status.ACK} upon receipt and a {@link Status.DONE} once all handlers have
- * finished processing.
- *
- * @param event - The MessageEvent.
- *
- */
- async handleEvent(event) {
- const messageEvent = event;
- const { eventId, eventType, data } = messageEvent.data;
- const handlers = this.handlersMap[eventType];
- if (!(handlers === null || handlers === void 0 ? void 0 : handlers.size)) {
- return;
- }
- messageEvent.ports[0].postMessage({
- status: "ack" /* _Status.ACK */,
- eventId,
- eventType
- });
- const promises = Array.from(handlers).map(async (handler) => handler(messageEvent.origin, data));
- const response = await _allSettled(promises);
- messageEvent.ports[0].postMessage({
- status: "done" /* _Status.DONE */,
- eventId,
- eventType,
- response
- });
- }
- /**
- * Subscribe an event handler for a particular event.
- *
- * @param eventType - Event name to subscribe to.
- * @param eventHandler - The event handler which should receive the events.
- *
- */
- _subscribe(eventType, eventHandler) {
- if (Object.keys(this.handlersMap).length === 0) {
- this.eventTarget.addEventListener('message', this.boundEventHandler);
- }
- if (!this.handlersMap[eventType]) {
- this.handlersMap[eventType] = new Set();
- }
- this.handlersMap[eventType].add(eventHandler);
- }
- /**
- * Unsubscribe an event handler from a particular event.
- *
- * @param eventType - Event name to unsubscribe from.
- * @param eventHandler - Optinoal event handler, if none provided, unsubscribe all handlers on this event.
- *
- */
- _unsubscribe(eventType, eventHandler) {
- if (this.handlersMap[eventType] && eventHandler) {
- this.handlersMap[eventType].delete(eventHandler);
- }
- if (!eventHandler || this.handlersMap[eventType].size === 0) {
- delete this.handlersMap[eventType];
- }
- if (Object.keys(this.handlersMap).length === 0) {
- this.eventTarget.removeEventListener('message', this.boundEventHandler);
- }
- }
- }
- Receiver.receivers = [];
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _generateEventId(prefix = '', digits = 10) {
- let random = '';
- for (let i = 0; i < digits; i++) {
- random += Math.floor(Math.random() * 10);
- }
- return prefix + random;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Interface for sending messages and waiting for a completion response.
- *
- */
- class Sender {
- constructor(target) {
- this.target = target;
- this.handlers = new Set();
- }
- /**
- * Unsubscribe the handler and remove it from our tracking Set.
- *
- * @param handler - The handler to unsubscribe.
- */
- removeMessageHandler(handler) {
- if (handler.messageChannel) {
- handler.messageChannel.port1.removeEventListener('message', handler.onMessage);
- handler.messageChannel.port1.close();
- }
- this.handlers.delete(handler);
- }
- /**
- * Send a message to the Receiver located at {@link target}.
- *
- * @remarks
- * We'll first wait a bit for an ACK , if we get one we will wait significantly longer until the
- * receiver has had a chance to fully process the event.
- *
- * @param eventType - Type of event to send.
- * @param data - The payload of the event.
- * @param timeout - Timeout for waiting on an ACK from the receiver.
- *
- * @returns An array of settled promises from all the handlers that were listening on the receiver.
- */
- async _send(eventType, data, timeout = 50 /* _TimeoutDuration.ACK */) {
- const messageChannel = typeof MessageChannel !== 'undefined' ? new MessageChannel() : null;
- if (!messageChannel) {
- throw new Error("connection_unavailable" /* _MessageError.CONNECTION_UNAVAILABLE */);
- }
- // Node timers and browser timers return fundamentally different types.
- // We don't actually care what the value is but TS won't accept unknown and
- // we can't cast properly in both environments.
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- let completionTimer;
- let handler;
- return new Promise((resolve, reject) => {
- const eventId = _generateEventId('', 20);
- messageChannel.port1.start();
- const ackTimer = setTimeout(() => {
- reject(new Error("unsupported_event" /* _MessageError.UNSUPPORTED_EVENT */));
- }, timeout);
- handler = {
- messageChannel,
- onMessage(event) {
- const messageEvent = event;
- if (messageEvent.data.eventId !== eventId) {
- return;
- }
- switch (messageEvent.data.status) {
- case "ack" /* _Status.ACK */:
- // The receiver should ACK first.
- clearTimeout(ackTimer);
- completionTimer = setTimeout(() => {
- reject(new Error("timeout" /* _MessageError.TIMEOUT */));
- }, 3000 /* _TimeoutDuration.COMPLETION */);
- break;
- case "done" /* _Status.DONE */:
- // Once the receiver's handlers are finished we will get the results.
- clearTimeout(completionTimer);
- resolve(messageEvent.data.response);
- break;
- default:
- clearTimeout(ackTimer);
- clearTimeout(completionTimer);
- reject(new Error("invalid_response" /* _MessageError.INVALID_RESPONSE */));
- break;
- }
- }
- };
- this.handlers.add(handler);
- messageChannel.port1.addEventListener('message', handler.onMessage);
- this.target.postMessage({
- eventType,
- eventId,
- data
- }, [messageChannel.port2]);
- }).finally(() => {
- if (handler) {
- this.removeMessageHandler(handler);
- }
- });
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Lazy accessor for window, since the compat layer won't tree shake this out,
- * we need to make sure not to mess with window unless we have to
- */
- function _window() {
- return window;
- }
- function _setWindowLocation(url) {
- _window().location.href = url;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _isWorker$1() {
- return (typeof _window()['WorkerGlobalScope'] !== 'undefined' &&
- typeof _window()['importScripts'] === 'function');
- }
- async function _getActiveServiceWorker() {
- if (!(navigator === null || navigator === void 0 ? void 0 : navigator.serviceWorker)) {
- return null;
- }
- try {
- const registration = await navigator.serviceWorker.ready;
- return registration.active;
- }
- catch (_a) {
- return null;
- }
- }
- function _getServiceWorkerController() {
- var _a;
- return ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.serviceWorker) === null || _a === void 0 ? void 0 : _a.controller) || null;
- }
- function _getWorkerGlobalScope() {
- return _isWorker$1() ? self : null;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const DB_NAME = 'firebaseLocalStorageDb';
- const DB_VERSION = 1;
- const DB_OBJECTSTORE_NAME = 'firebaseLocalStorage';
- const DB_DATA_KEYPATH = 'fbase_key';
- /**
- * Promise wrapper for IDBRequest
- *
- * Unfortunately we can't cleanly extend Promise since promises are not callable in ES6
- *
- */
- class DBPromise {
- constructor(request) {
- this.request = request;
- }
- toPromise() {
- return new Promise((resolve, reject) => {
- this.request.addEventListener('success', () => {
- resolve(this.request.result);
- });
- this.request.addEventListener('error', () => {
- reject(this.request.error);
- });
- });
- }
- }
- function getObjectStore(db, isReadWrite) {
- return db
- .transaction([DB_OBJECTSTORE_NAME], isReadWrite ? 'readwrite' : 'readonly')
- .objectStore(DB_OBJECTSTORE_NAME);
- }
- function _deleteDatabase() {
- const request = indexedDB.deleteDatabase(DB_NAME);
- return new DBPromise(request).toPromise();
- }
- function _openDatabase() {
- const request = indexedDB.open(DB_NAME, DB_VERSION);
- return new Promise((resolve, reject) => {
- request.addEventListener('error', () => {
- reject(request.error);
- });
- request.addEventListener('upgradeneeded', () => {
- const db = request.result;
- try {
- db.createObjectStore(DB_OBJECTSTORE_NAME, { keyPath: DB_DATA_KEYPATH });
- }
- catch (e) {
- reject(e);
- }
- });
- request.addEventListener('success', async () => {
- const db = request.result;
- // Strange bug that occurs in Firefox when multiple tabs are opened at the
- // same time. The only way to recover seems to be deleting the database
- // and re-initializing it.
- // https://github.com/firebase/firebase-js-sdk/issues/634
- if (!db.objectStoreNames.contains(DB_OBJECTSTORE_NAME)) {
- // Need to close the database or else you get a `blocked` event
- db.close();
- await _deleteDatabase();
- resolve(await _openDatabase());
- }
- else {
- resolve(db);
- }
- });
- });
- }
- async function _putObject(db, key, value) {
- const request = getObjectStore(db, true).put({
- [DB_DATA_KEYPATH]: key,
- value
- });
- return new DBPromise(request).toPromise();
- }
- async function getObject(db, key) {
- const request = getObjectStore(db, false).get(key);
- const data = await new DBPromise(request).toPromise();
- return data === undefined ? null : data.value;
- }
- function _deleteObject(db, key) {
- const request = getObjectStore(db, true).delete(key);
- return new DBPromise(request).toPromise();
- }
- const _POLLING_INTERVAL_MS = 800;
- const _TRANSACTION_RETRY_COUNT = 3;
- class IndexedDBLocalPersistence {
- constructor() {
- this.type = "LOCAL" /* PersistenceType.LOCAL */;
- this._shouldAllowMigration = true;
- this.listeners = {};
- this.localCache = {};
- // setTimeout return value is platform specific
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- this.pollTimer = null;
- this.pendingWrites = 0;
- this.receiver = null;
- this.sender = null;
- this.serviceWorkerReceiverAvailable = false;
- this.activeServiceWorker = null;
- // Fire & forget the service worker registration as it may never resolve
- this._workerInitializationPromise =
- this.initializeServiceWorkerMessaging().then(() => { }, () => { });
- }
- async _openDb() {
- if (this.db) {
- return this.db;
- }
- this.db = await _openDatabase();
- return this.db;
- }
- async _withRetries(op) {
- let numAttempts = 0;
- while (true) {
- try {
- const db = await this._openDb();
- return await op(db);
- }
- catch (e) {
- if (numAttempts++ > _TRANSACTION_RETRY_COUNT) {
- throw e;
- }
- if (this.db) {
- this.db.close();
- this.db = undefined;
- }
- // TODO: consider adding exponential backoff
- }
- }
- }
- /**
- * IndexedDB events do not propagate from the main window to the worker context. We rely on a
- * postMessage interface to send these events to the worker ourselves.
- */
- async initializeServiceWorkerMessaging() {
- return _isWorker$1() ? this.initializeReceiver() : this.initializeSender();
- }
- /**
- * As the worker we should listen to events from the main window.
- */
- async initializeReceiver() {
- this.receiver = Receiver._getInstance(_getWorkerGlobalScope());
- // Refresh from persistence if we receive a KeyChanged message.
- this.receiver._subscribe("keyChanged" /* _EventType.KEY_CHANGED */, async (_origin, data) => {
- const keys = await this._poll();
- return {
- keyProcessed: keys.includes(data.key)
- };
- });
- // Let the sender know that we are listening so they give us more timeout.
- this.receiver._subscribe("ping" /* _EventType.PING */, async (_origin, _data) => {
- return ["keyChanged" /* _EventType.KEY_CHANGED */];
- });
- }
- /**
- * As the main window, we should let the worker know when keys change (set and remove).
- *
- * @remarks
- * {@link https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/ready | ServiceWorkerContainer.ready}
- * may not resolve.
- */
- async initializeSender() {
- var _a, _b;
- // Check to see if there's an active service worker.
- this.activeServiceWorker = await _getActiveServiceWorker();
- if (!this.activeServiceWorker) {
- return;
- }
- this.sender = new Sender(this.activeServiceWorker);
- // Ping the service worker to check what events they can handle.
- const results = await this.sender._send("ping" /* _EventType.PING */, {}, 800 /* _TimeoutDuration.LONG_ACK */);
- if (!results) {
- return;
- }
- if (((_a = results[0]) === null || _a === void 0 ? void 0 : _a.fulfilled) &&
- ((_b = results[0]) === null || _b === void 0 ? void 0 : _b.value.includes("keyChanged" /* _EventType.KEY_CHANGED */))) {
- this.serviceWorkerReceiverAvailable = true;
- }
- }
- /**
- * Let the worker know about a changed key, the exact key doesn't technically matter since the
- * worker will just trigger a full sync anyway.
- *
- * @remarks
- * For now, we only support one service worker per page.
- *
- * @param key - Storage key which changed.
- */
- async notifyServiceWorker(key) {
- if (!this.sender ||
- !this.activeServiceWorker ||
- _getServiceWorkerController() !== this.activeServiceWorker) {
- return;
- }
- try {
- await this.sender._send("keyChanged" /* _EventType.KEY_CHANGED */, { key },
- // Use long timeout if receiver has previously responded to a ping from us.
- this.serviceWorkerReceiverAvailable
- ? 800 /* _TimeoutDuration.LONG_ACK */
- : 50 /* _TimeoutDuration.ACK */);
- }
- catch (_a) {
- // This is a best effort approach. Ignore errors.
- }
- }
- async _isAvailable() {
- try {
- if (!indexedDB) {
- return false;
- }
- const db = await _openDatabase();
- await _putObject(db, STORAGE_AVAILABLE_KEY, '1');
- await _deleteObject(db, STORAGE_AVAILABLE_KEY);
- return true;
- }
- catch (_a) { }
- return false;
- }
- async _withPendingWrite(write) {
- this.pendingWrites++;
- try {
- await write();
- }
- finally {
- this.pendingWrites--;
- }
- }
- async _set(key, value) {
- return this._withPendingWrite(async () => {
- await this._withRetries((db) => _putObject(db, key, value));
- this.localCache[key] = value;
- return this.notifyServiceWorker(key);
- });
- }
- async _get(key) {
- const obj = (await this._withRetries((db) => getObject(db, key)));
- this.localCache[key] = obj;
- return obj;
- }
- async _remove(key) {
- return this._withPendingWrite(async () => {
- await this._withRetries((db) => _deleteObject(db, key));
- delete this.localCache[key];
- return this.notifyServiceWorker(key);
- });
- }
- async _poll() {
- // TODO: check if we need to fallback if getAll is not supported
- const result = await this._withRetries((db) => {
- const getAllRequest = getObjectStore(db, false).getAll();
- return new DBPromise(getAllRequest).toPromise();
- });
- if (!result) {
- return [];
- }
- // If we have pending writes in progress abort, we'll get picked up on the next poll
- if (this.pendingWrites !== 0) {
- return [];
- }
- const keys = [];
- const keysInResult = new Set();
- for (const { fbase_key: key, value } of result) {
- keysInResult.add(key);
- if (JSON.stringify(this.localCache[key]) !== JSON.stringify(value)) {
- this.notifyListeners(key, value);
- keys.push(key);
- }
- }
- for (const localKey of Object.keys(this.localCache)) {
- if (this.localCache[localKey] && !keysInResult.has(localKey)) {
- // Deleted
- this.notifyListeners(localKey, null);
- keys.push(localKey);
- }
- }
- return keys;
- }
- notifyListeners(key, newValue) {
- this.localCache[key] = newValue;
- const listeners = this.listeners[key];
- if (listeners) {
- for (const listener of Array.from(listeners)) {
- listener(newValue);
- }
- }
- }
- startPolling() {
- this.stopPolling();
- this.pollTimer = setInterval(async () => this._poll(), _POLLING_INTERVAL_MS);
- }
- stopPolling() {
- if (this.pollTimer) {
- clearInterval(this.pollTimer);
- this.pollTimer = null;
- }
- }
- _addListener(key, listener) {
- if (Object.keys(this.listeners).length === 0) {
- this.startPolling();
- }
- if (!this.listeners[key]) {
- this.listeners[key] = new Set();
- // Populate the cache to avoid spuriously triggering on first poll.
- void this._get(key); // This can happen in the background async and we can return immediately.
- }
- this.listeners[key].add(listener);
- }
- _removeListener(key, listener) {
- if (this.listeners[key]) {
- this.listeners[key].delete(listener);
- if (this.listeners[key].size === 0) {
- delete this.listeners[key];
- }
- }
- if (Object.keys(this.listeners).length === 0) {
- this.stopPolling();
- }
- }
- }
- IndexedDBLocalPersistence.type = 'LOCAL';
- /**
- * An implementation of {@link Persistence} of type `LOCAL` using `indexedDB`
- * for the underlying storage.
- *
- * @public
- */
- const indexedDBLocalPersistence = IndexedDBLocalPersistence;
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function startSignInPhoneMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaSignIn:start" /* Endpoint.START_MFA_SIGN_IN */, _addTidIfNecessary(auth, request));
- }
- function finalizeSignInPhoneMfa(auth, request) {
- return _performApiRequest(auth, "POST" /* HttpMethod.POST */, "/v2/accounts/mfaSignIn:finalize" /* Endpoint.FINALIZE_MFA_SIGN_IN */, _addTidIfNecessary(auth, request));
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const _SOLVE_TIME_MS = 500;
- const _EXPIRATION_TIME_MS = 60000;
- const _WIDGET_ID_START = 1000000000000;
- class MockReCaptcha {
- constructor(auth) {
- this.auth = auth;
- this.counter = _WIDGET_ID_START;
- this._widgets = new Map();
- }
- render(container, parameters) {
- const id = this.counter;
- this._widgets.set(id, new MockWidget(container, this.auth.name, parameters || {}));
- this.counter++;
- return id;
- }
- reset(optWidgetId) {
- var _a;
- const id = optWidgetId || _WIDGET_ID_START;
- void ((_a = this._widgets.get(id)) === null || _a === void 0 ? void 0 : _a.delete());
- this._widgets.delete(id);
- }
- getResponse(optWidgetId) {
- var _a;
- const id = optWidgetId || _WIDGET_ID_START;
- return ((_a = this._widgets.get(id)) === null || _a === void 0 ? void 0 : _a.getResponse()) || '';
- }
- async execute(optWidgetId) {
- var _a;
- const id = optWidgetId || _WIDGET_ID_START;
- void ((_a = this._widgets.get(id)) === null || _a === void 0 ? void 0 : _a.execute());
- return '';
- }
- }
- class MockWidget {
- constructor(containerOrId, appName, params) {
- this.params = params;
- this.timerId = null;
- this.deleted = false;
- this.responseToken = null;
- this.clickHandler = () => {
- this.execute();
- };
- const container = typeof containerOrId === 'string'
- ? document.getElementById(containerOrId)
- : containerOrId;
- _assert$4(container, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */, { appName });
- this.container = container;
- this.isVisible = this.params.size !== 'invisible';
- if (this.isVisible) {
- this.execute();
- }
- else {
- this.container.addEventListener('click', this.clickHandler);
- }
- }
- getResponse() {
- this.checkIfDeleted();
- return this.responseToken;
- }
- delete() {
- this.checkIfDeleted();
- this.deleted = true;
- if (this.timerId) {
- clearTimeout(this.timerId);
- this.timerId = null;
- }
- this.container.removeEventListener('click', this.clickHandler);
- }
- execute() {
- this.checkIfDeleted();
- if (this.timerId) {
- return;
- }
- this.timerId = window.setTimeout(() => {
- this.responseToken = generateRandomAlphaNumericString(50);
- const { callback, 'expired-callback': expiredCallback } = this.params;
- if (callback) {
- try {
- callback(this.responseToken);
- }
- catch (e) { }
- }
- this.timerId = window.setTimeout(() => {
- this.timerId = null;
- this.responseToken = null;
- if (expiredCallback) {
- try {
- expiredCallback();
- }
- catch (e) { }
- }
- if (this.isVisible) {
- this.execute();
- }
- }, _EXPIRATION_TIME_MS);
- }, _SOLVE_TIME_MS);
- }
- checkIfDeleted() {
- if (this.deleted) {
- throw new Error('reCAPTCHA mock was already deleted!');
- }
- }
- }
- function generateRandomAlphaNumericString(len) {
- const chars = [];
- const allowedChars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
- for (let i = 0; i < len; i++) {
- chars.push(allowedChars.charAt(Math.floor(Math.random() * allowedChars.length)));
- }
- return chars.join('');
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // ReCaptcha will load using the same callback, so the callback function needs
- // to be kept around
- const _JSLOAD_CALLBACK = _generateCallbackName('rcb');
- const NETWORK_TIMEOUT_DELAY = new Delay(30000, 60000);
- const RECAPTCHA_BASE = 'https://www.google.com/recaptcha/api.js?';
- /**
- * Loader for the GReCaptcha library. There should only ever be one of this.
- */
- class ReCaptchaLoaderImpl {
- constructor() {
- var _a;
- this.hostLanguage = '';
- this.counter = 0;
- /**
- * Check for `render()` method. `window.grecaptcha` will exist if the Enterprise
- * version of the ReCAPTCHA script was loaded by someone else (e.g. App Check) but
- * `window.grecaptcha.render()` will not. Another load will add it.
- */
- this.librarySeparatelyLoaded = !!((_a = _window().grecaptcha) === null || _a === void 0 ? void 0 : _a.render);
- }
- load(auth, hl = '') {
- _assert$4(isHostLanguageValid(hl), auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- if (this.shouldResolveImmediately(hl) && isV2(_window().grecaptcha)) {
- return Promise.resolve(_window().grecaptcha);
- }
- return new Promise((resolve, reject) => {
- const networkTimeout = _window().setTimeout(() => {
- reject(_createError(auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */));
- }, NETWORK_TIMEOUT_DELAY.get());
- _window()[_JSLOAD_CALLBACK] = () => {
- _window().clearTimeout(networkTimeout);
- delete _window()[_JSLOAD_CALLBACK];
- const recaptcha = _window().grecaptcha;
- if (!recaptcha || !isV2(recaptcha)) {
- reject(_createError(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */));
- return;
- }
- // Wrap the greptcha render function so that we know if the developer has
- // called it separately
- const render = recaptcha.render;
- recaptcha.render = (container, params) => {
- const widgetId = render(container, params);
- this.counter++;
- return widgetId;
- };
- this.hostLanguage = hl;
- resolve(recaptcha);
- };
- const url = `${RECAPTCHA_BASE}?${querystring({
- onload: _JSLOAD_CALLBACK,
- render: 'explicit',
- hl
- })}`;
- _loadJS(url).catch(() => {
- clearTimeout(networkTimeout);
- reject(_createError(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */));
- });
- });
- }
- clearedOneInstance() {
- this.counter--;
- }
- shouldResolveImmediately(hl) {
- var _a;
- // We can resolve immediately if:
- // • grecaptcha is already defined AND (
- // 1. the requested language codes are the same OR
- // 2. there exists already a ReCaptcha on the page
- // 3. the library was already loaded by the app
- // In cases (2) and (3), we _can't_ reload as it would break the recaptchas
- // that are already in the page
- return (!!((_a = _window().grecaptcha) === null || _a === void 0 ? void 0 : _a.render) &&
- (hl === this.hostLanguage ||
- this.counter > 0 ||
- this.librarySeparatelyLoaded));
- }
- }
- function isHostLanguageValid(hl) {
- return hl.length <= 6 && /^\s*[a-zA-Z0-9\-]*\s*$/.test(hl);
- }
- class MockReCaptchaLoaderImpl {
- async load(auth) {
- return new MockReCaptcha(auth);
- }
- clearedOneInstance() { }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const RECAPTCHA_VERIFIER_TYPE = 'recaptcha';
- const DEFAULT_PARAMS = {
- theme: 'light',
- type: 'image'
- };
- /**
- * An {@link https://www.google.com/recaptcha/ | reCAPTCHA}-based application verifier.
- *
- * @public
- */
- class RecaptchaVerifier$1 {
- /**
- *
- * @param containerOrId - The reCAPTCHA container parameter.
- *
- * @remarks
- * This has different meaning depending on whether the reCAPTCHA is hidden or visible. For a
- * visible reCAPTCHA the container must be empty. If a string is used, it has to correspond to
- * an element ID. The corresponding element must also must be in the DOM at the time of
- * initialization.
- *
- * @param parameters - The optional reCAPTCHA parameters.
- *
- * @remarks
- * Check the reCAPTCHA docs for a comprehensive list. All parameters are accepted except for
- * the sitekey. Firebase Auth backend provisions a reCAPTCHA for each project and will
- * configure this upon rendering. For an invisible reCAPTCHA, a size key must have the value
- * 'invisible'.
- *
- * @param authExtern - The corresponding Firebase {@link Auth} instance.
- */
- constructor(containerOrId, parameters = Object.assign({}, DEFAULT_PARAMS), authExtern) {
- this.parameters = parameters;
- /**
- * The application verifier type.
- *
- * @remarks
- * For a reCAPTCHA verifier, this is 'recaptcha'.
- */
- this.type = RECAPTCHA_VERIFIER_TYPE;
- this.destroyed = false;
- this.widgetId = null;
- this.tokenChangeListeners = new Set();
- this.renderPromise = null;
- this.recaptcha = null;
- this.auth = _castAuth(authExtern);
- this.isInvisible = this.parameters.size === 'invisible';
- _assert$4(typeof document !== 'undefined', this.auth, "operation-not-supported-in-this-environment" /* AuthErrorCode.OPERATION_NOT_SUPPORTED */);
- const container = typeof containerOrId === 'string'
- ? document.getElementById(containerOrId)
- : containerOrId;
- _assert$4(container, this.auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- this.container = container;
- this.parameters.callback = this.makeTokenCallback(this.parameters.callback);
- this._recaptchaLoader = this.auth.settings.appVerificationDisabledForTesting
- ? new MockReCaptchaLoaderImpl()
- : new ReCaptchaLoaderImpl();
- this.validateStartingState();
- // TODO: Figure out if sdk version is needed
- }
- /**
- * Waits for the user to solve the reCAPTCHA and resolves with the reCAPTCHA token.
- *
- * @returns A Promise for the reCAPTCHA token.
- */
- async verify() {
- this.assertNotDestroyed();
- const id = await this.render();
- const recaptcha = this.getAssertedRecaptcha();
- const response = recaptcha.getResponse(id);
- if (response) {
- return response;
- }
- return new Promise(resolve => {
- const tokenChange = (token) => {
- if (!token) {
- return; // Ignore token expirations.
- }
- this.tokenChangeListeners.delete(tokenChange);
- resolve(token);
- };
- this.tokenChangeListeners.add(tokenChange);
- if (this.isInvisible) {
- recaptcha.execute(id);
- }
- });
- }
- /**
- * Renders the reCAPTCHA widget on the page.
- *
- * @returns A Promise that resolves with the reCAPTCHA widget ID.
- */
- render() {
- try {
- this.assertNotDestroyed();
- }
- catch (e) {
- // This method returns a promise. Since it's not async (we want to return the
- // _same_ promise if rendering is still occurring), the API surface should
- // reject with the error rather than just throw
- return Promise.reject(e);
- }
- if (this.renderPromise) {
- return this.renderPromise;
- }
- this.renderPromise = this.makeRenderPromise().catch(e => {
- this.renderPromise = null;
- throw e;
- });
- return this.renderPromise;
- }
- /** @internal */
- _reset() {
- this.assertNotDestroyed();
- if (this.widgetId !== null) {
- this.getAssertedRecaptcha().reset(this.widgetId);
- }
- }
- /**
- * Clears the reCAPTCHA widget from the page and destroys the instance.
- */
- clear() {
- this.assertNotDestroyed();
- this.destroyed = true;
- this._recaptchaLoader.clearedOneInstance();
- if (!this.isInvisible) {
- this.container.childNodes.forEach(node => {
- this.container.removeChild(node);
- });
- }
- }
- validateStartingState() {
- _assert$4(!this.parameters.sitekey, this.auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- _assert$4(this.isInvisible || !this.container.hasChildNodes(), this.auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- _assert$4(typeof document !== 'undefined', this.auth, "operation-not-supported-in-this-environment" /* AuthErrorCode.OPERATION_NOT_SUPPORTED */);
- }
- makeTokenCallback(existing) {
- return token => {
- this.tokenChangeListeners.forEach(listener => listener(token));
- if (typeof existing === 'function') {
- existing(token);
- }
- else if (typeof existing === 'string') {
- const globalFunc = _window()[existing];
- if (typeof globalFunc === 'function') {
- globalFunc(token);
- }
- }
- };
- }
- assertNotDestroyed() {
- _assert$4(!this.destroyed, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- async makeRenderPromise() {
- await this.init();
- if (!this.widgetId) {
- let container = this.container;
- if (!this.isInvisible) {
- const guaranteedEmpty = document.createElement('div');
- container.appendChild(guaranteedEmpty);
- container = guaranteedEmpty;
- }
- this.widgetId = this.getAssertedRecaptcha().render(container, this.parameters);
- }
- return this.widgetId;
- }
- async init() {
- _assert$4(_isHttpOrHttps$1() && !_isWorker$1(), this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- await domReady();
- this.recaptcha = await this._recaptchaLoader.load(this.auth, this.auth.languageCode || undefined);
- const siteKey = await getRecaptchaParams(this.auth);
- _assert$4(siteKey, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- this.parameters.sitekey = siteKey;
- }
- getAssertedRecaptcha() {
- _assert$4(this.recaptcha, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return this.recaptcha;
- }
- }
- function domReady() {
- let resolver = null;
- return new Promise(resolve => {
- if (document.readyState === 'complete') {
- resolve();
- return;
- }
- // Document not ready, wait for load before resolving.
- // Save resolver, so we can remove listener in case it was externally
- // cancelled.
- resolver = () => resolve();
- window.addEventListener('load', resolver);
- }).catch(e => {
- if (resolver) {
- window.removeEventListener('load', resolver);
- }
- throw e;
- });
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class ConfirmationResultImpl {
- constructor(verificationId, onConfirmation) {
- this.verificationId = verificationId;
- this.onConfirmation = onConfirmation;
- }
- confirm(verificationCode) {
- const authCredential = PhoneAuthCredential._fromVerification(this.verificationId, verificationCode);
- return this.onConfirmation(authCredential);
- }
- }
- /**
- * Asynchronously signs in using a phone number.
- *
- * @remarks
- * This method sends a code via SMS to the given
- * phone number, and returns a {@link ConfirmationResult}. After the user
- * provides the code sent to their phone, call {@link ConfirmationResult.confirm}
- * with the code to sign the user in.
- *
- * For abuse prevention, this method also requires a {@link ApplicationVerifier}.
- * This SDK includes a reCAPTCHA-based implementation, {@link RecaptchaVerifier}.
- * This function can work on other platforms that do not support the
- * {@link RecaptchaVerifier} (like React Native), but you need to use a
- * third-party {@link ApplicationVerifier} implementation.
- *
- * @example
- * ```javascript
- * // 'recaptcha-container' is the ID of an element in the DOM.
- * const applicationVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
- * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier);
- * // Obtain a verificationCode from the user.
- * const credential = await confirmationResult.confirm(verificationCode);
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101).
- * @param appVerifier - The {@link ApplicationVerifier}.
- *
- * @public
- */
- async function signInWithPhoneNumber(auth, phoneNumber, appVerifier) {
- const authInternal = _castAuth(auth);
- const verificationId = await _verifyPhoneNumber(authInternal, phoneNumber, getModularInstance(appVerifier));
- return new ConfirmationResultImpl(verificationId, cred => signInWithCredential(authInternal, cred));
- }
- /**
- * Links the user account with the given phone number.
- *
- * @param user - The user.
- * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101).
- * @param appVerifier - The {@link ApplicationVerifier}.
- *
- * @public
- */
- async function linkWithPhoneNumber(user, phoneNumber, appVerifier) {
- const userInternal = getModularInstance(user);
- await _assertLinkedStatus(false, userInternal, "phone" /* ProviderId.PHONE */);
- const verificationId = await _verifyPhoneNumber(userInternal.auth, phoneNumber, getModularInstance(appVerifier));
- return new ConfirmationResultImpl(verificationId, cred => linkWithCredential(userInternal, cred));
- }
- /**
- * Re-authenticates a user using a fresh phone credential.
- *
- * @remarks Use before operations such as {@link updatePassword} that require tokens from recent sign-in attempts.
- *
- * @param user - The user.
- * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101).
- * @param appVerifier - The {@link ApplicationVerifier}.
- *
- * @public
- */
- async function reauthenticateWithPhoneNumber(user, phoneNumber, appVerifier) {
- const userInternal = getModularInstance(user);
- const verificationId = await _verifyPhoneNumber(userInternal.auth, phoneNumber, getModularInstance(appVerifier));
- return new ConfirmationResultImpl(verificationId, cred => reauthenticateWithCredential(userInternal, cred));
- }
- /**
- * Returns a verification ID to be used in conjunction with the SMS code that is sent.
- *
- */
- async function _verifyPhoneNumber(auth, options, verifier) {
- var _a;
- const recaptchaToken = await verifier.verify();
- try {
- _assert$4(typeof recaptchaToken === 'string', auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- _assert$4(verifier.type === RECAPTCHA_VERIFIER_TYPE, auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- let phoneInfoOptions;
- if (typeof options === 'string') {
- phoneInfoOptions = {
- phoneNumber: options
- };
- }
- else {
- phoneInfoOptions = options;
- }
- if ('session' in phoneInfoOptions) {
- const session = phoneInfoOptions.session;
- if ('phoneNumber' in phoneInfoOptions) {
- _assert$4(session.type === "enroll" /* MultiFactorSessionType.ENROLL */, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const response = await startEnrollPhoneMfa(auth, {
- idToken: session.credential,
- phoneEnrollmentInfo: {
- phoneNumber: phoneInfoOptions.phoneNumber,
- recaptchaToken
- }
- });
- return response.phoneSessionInfo.sessionInfo;
- }
- else {
- _assert$4(session.type === "signin" /* MultiFactorSessionType.SIGN_IN */, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- const mfaEnrollmentId = ((_a = phoneInfoOptions.multiFactorHint) === null || _a === void 0 ? void 0 : _a.uid) ||
- phoneInfoOptions.multiFactorUid;
- _assert$4(mfaEnrollmentId, auth, "missing-multi-factor-info" /* AuthErrorCode.MISSING_MFA_INFO */);
- const response = await startSignInPhoneMfa(auth, {
- mfaPendingCredential: session.credential,
- mfaEnrollmentId,
- phoneSignInInfo: {
- recaptchaToken
- }
- });
- return response.phoneResponseInfo.sessionInfo;
- }
- }
- else {
- const { sessionInfo } = await sendPhoneVerificationCode(auth, {
- phoneNumber: phoneInfoOptions.phoneNumber,
- recaptchaToken
- });
- return sessionInfo;
- }
- }
- finally {
- verifier._reset();
- }
- }
- /**
- * Updates the user's phone number.
- *
- * @example
- * ```
- * // 'recaptcha-container' is the ID of an element in the DOM.
- * const applicationVerifier = new RecaptchaVerifier('recaptcha-container');
- * const provider = new PhoneAuthProvider(auth);
- * const verificationId = await provider.verifyPhoneNumber('+16505550101', applicationVerifier);
- * // Obtain the verificationCode from the user.
- * const phoneCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
- * await updatePhoneNumber(user, phoneCredential);
- * ```
- *
- * @param user - The user.
- * @param credential - A credential authenticating the new phone number.
- *
- * @public
- */
- async function updatePhoneNumber(user, credential) {
- await _link$1(getModularInstance(user), credential);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Provider for generating an {@link PhoneAuthCredential}.
- *
- * @example
- * ```javascript
- * // 'recaptcha-container' is the ID of an element in the DOM.
- * const applicationVerifier = new RecaptchaVerifier('recaptcha-container');
- * const provider = new PhoneAuthProvider(auth);
- * const verificationId = await provider.verifyPhoneNumber('+16505550101', applicationVerifier);
- * // Obtain the verificationCode from the user.
- * const phoneCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
- * const userCredential = await signInWithCredential(auth, phoneCredential);
- * ```
- *
- * @public
- */
- class PhoneAuthProvider$1 {
- /**
- * @param auth - The Firebase {@link Auth} instance in which sign-ins should occur.
- *
- */
- constructor(auth) {
- /** Always set to {@link ProviderId}.PHONE. */
- this.providerId = PhoneAuthProvider$1.PROVIDER_ID;
- this.auth = _castAuth(auth);
- }
- /**
- *
- * Starts a phone number authentication flow by sending a verification code to the given phone
- * number.
- *
- * @example
- * ```javascript
- * const provider = new PhoneAuthProvider(auth);
- * const verificationId = await provider.verifyPhoneNumber(phoneNumber, applicationVerifier);
- * // Obtain verificationCode from the user.
- * const authCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
- * const userCredential = await signInWithCredential(auth, authCredential);
- * ```
- *
- * @example
- * An alternative flow is provided using the `signInWithPhoneNumber` method.
- * ```javascript
- * const confirmationResult = signInWithPhoneNumber(auth, phoneNumber, applicationVerifier);
- * // Obtain verificationCode from the user.
- * const userCredential = confirmationResult.confirm(verificationCode);
- * ```
- *
- * @param phoneInfoOptions - The user's {@link PhoneInfoOptions}. The phone number should be in
- * E.164 format (e.g. +16505550101).
- * @param applicationVerifier - For abuse prevention, this method also requires a
- * {@link ApplicationVerifier}. This SDK includes a reCAPTCHA-based implementation,
- * {@link RecaptchaVerifier}.
- *
- * @returns A Promise for a verification ID that can be passed to
- * {@link PhoneAuthProvider.credential} to identify this flow..
- */
- verifyPhoneNumber(phoneOptions, applicationVerifier) {
- return _verifyPhoneNumber(this.auth, phoneOptions, getModularInstance(applicationVerifier));
- }
- /**
- * Creates a phone auth credential, given the verification ID from
- * {@link PhoneAuthProvider.verifyPhoneNumber} and the code that was sent to the user's
- * mobile device.
- *
- * @example
- * ```javascript
- * const provider = new PhoneAuthProvider(auth);
- * const verificationId = provider.verifyPhoneNumber(phoneNumber, applicationVerifier);
- * // Obtain verificationCode from the user.
- * const authCredential = PhoneAuthProvider.credential(verificationId, verificationCode);
- * const userCredential = signInWithCredential(auth, authCredential);
- * ```
- *
- * @example
- * An alternative flow is provided using the `signInWithPhoneNumber` method.
- * ```javascript
- * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier);
- * // Obtain verificationCode from the user.
- * const userCredential = await confirmationResult.confirm(verificationCode);
- * ```
- *
- * @param verificationId - The verification ID returned from {@link PhoneAuthProvider.verifyPhoneNumber}.
- * @param verificationCode - The verification code sent to the user's mobile device.
- *
- * @returns The auth provider credential.
- */
- static credential(verificationId, verificationCode) {
- return PhoneAuthCredential._fromVerification(verificationId, verificationCode);
- }
- /**
- * Generates an {@link AuthCredential} from a {@link UserCredential}.
- * @param userCredential - The user credential.
- */
- static credentialFromResult(userCredential) {
- const credential = userCredential;
- return PhoneAuthProvider$1.credentialFromTaggedObject(credential);
- }
- /**
- * Returns an {@link AuthCredential} when passed an error.
- *
- * @remarks
- *
- * This method works for errors like
- * `auth/account-exists-with-different-credentials`. This is useful for
- * recovering when attempting to set a user's phone number but the number
- * in question is already tied to another account. For example, the following
- * code tries to update the current user's phone number, and if that
- * fails, links the user with the account associated with that number:
- *
- * ```js
- * const provider = new PhoneAuthProvider(auth);
- * const verificationId = await provider.verifyPhoneNumber(number, verifier);
- * try {
- * const code = ''; // Prompt the user for the verification code
- * await updatePhoneNumber(
- * auth.currentUser,
- * PhoneAuthProvider.credential(verificationId, code));
- * } catch (e) {
- * if ((e as FirebaseError)?.code === 'auth/account-exists-with-different-credential') {
- * const cred = PhoneAuthProvider.credentialFromError(e);
- * await linkWithCredential(auth.currentUser, cred);
- * }
- * }
- *
- * // At this point, auth.currentUser.phoneNumber === number.
- * ```
- *
- * @param error - The error to generate a credential from.
- */
- static credentialFromError(error) {
- return PhoneAuthProvider$1.credentialFromTaggedObject((error.customData || {}));
- }
- static credentialFromTaggedObject({ _tokenResponse: tokenResponse }) {
- if (!tokenResponse) {
- return null;
- }
- const { phoneNumber, temporaryProof } = tokenResponse;
- if (phoneNumber && temporaryProof) {
- return PhoneAuthCredential._fromTokenResponse(phoneNumber, temporaryProof);
- }
- return null;
- }
- }
- /** Always set to {@link ProviderId}.PHONE. */
- PhoneAuthProvider$1.PROVIDER_ID = "phone" /* ProviderId.PHONE */;
- /** Always set to {@link SignInMethod}.PHONE. */
- PhoneAuthProvider$1.PHONE_SIGN_IN_METHOD = "phone" /* SignInMethod.PHONE */;
-
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Chooses a popup/redirect resolver to use. This prefers the override (which
- * is directly passed in), and falls back to the property set on the auth
- * object. If neither are available, this function errors w/ an argument error.
- */
- function _withDefaultResolver(auth, resolverOverride) {
- if (resolverOverride) {
- return _getInstance(resolverOverride);
- }
- _assert$4(auth._popupRedirectResolver, auth, "argument-error" /* AuthErrorCode.ARGUMENT_ERROR */);
- return auth._popupRedirectResolver;
- }
-
- /**
- * @license
- * Copyright 2019 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class IdpCredential extends AuthCredential {
- constructor(params) {
- super("custom" /* ProviderId.CUSTOM */, "custom" /* ProviderId.CUSTOM */);
- this.params = params;
- }
- _getIdTokenResponse(auth) {
- return signInWithIdp(auth, this._buildIdpRequest());
- }
- _linkToIdToken(auth, idToken) {
- return signInWithIdp(auth, this._buildIdpRequest(idToken));
- }
- _getReauthenticationResolver(auth) {
- return signInWithIdp(auth, this._buildIdpRequest());
- }
- _buildIdpRequest(idToken) {
- const request = {
- requestUri: this.params.requestUri,
- sessionId: this.params.sessionId,
- postBody: this.params.postBody,
- tenantId: this.params.tenantId,
- pendingToken: this.params.pendingToken,
- returnSecureToken: true,
- returnIdpCredential: true
- };
- if (idToken) {
- request.idToken = idToken;
- }
- return request;
- }
- }
- function _signIn(params) {
- return _signInWithCredential(params.auth, new IdpCredential(params), params.bypassAuthState);
- }
- function _reauth(params) {
- const { auth, user } = params;
- _assert$4(user, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return _reauthenticate(user, new IdpCredential(params), params.bypassAuthState);
- }
- async function _link(params) {
- const { auth, user } = params;
- _assert$4(user, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return _link$1(user, new IdpCredential(params), params.bypassAuthState);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Popup event manager. Handles the popup's entire lifecycle; listens to auth
- * events
- */
- class AbstractPopupRedirectOperation {
- constructor(auth, filter, resolver, user, bypassAuthState = false) {
- this.auth = auth;
- this.resolver = resolver;
- this.user = user;
- this.bypassAuthState = bypassAuthState;
- this.pendingPromise = null;
- this.eventManager = null;
- this.filter = Array.isArray(filter) ? filter : [filter];
- }
- execute() {
- return new Promise(async (resolve, reject) => {
- this.pendingPromise = { resolve, reject };
- try {
- this.eventManager = await this.resolver._initialize(this.auth);
- await this.onExecution();
- this.eventManager.registerConsumer(this);
- }
- catch (e) {
- this.reject(e);
- }
- });
- }
- async onAuthEvent(event) {
- const { urlResponse, sessionId, postBody, tenantId, error, type } = event;
- if (error) {
- this.reject(error);
- return;
- }
- const params = {
- auth: this.auth,
- requestUri: urlResponse,
- sessionId: sessionId,
- tenantId: tenantId || undefined,
- postBody: postBody || undefined,
- user: this.user,
- bypassAuthState: this.bypassAuthState
- };
- try {
- this.resolve(await this.getIdpTask(type)(params));
- }
- catch (e) {
- this.reject(e);
- }
- }
- onError(error) {
- this.reject(error);
- }
- getIdpTask(type) {
- switch (type) {
- case "signInViaPopup" /* AuthEventType.SIGN_IN_VIA_POPUP */:
- case "signInViaRedirect" /* AuthEventType.SIGN_IN_VIA_REDIRECT */:
- return _signIn;
- case "linkViaPopup" /* AuthEventType.LINK_VIA_POPUP */:
- case "linkViaRedirect" /* AuthEventType.LINK_VIA_REDIRECT */:
- return _link;
- case "reauthViaPopup" /* AuthEventType.REAUTH_VIA_POPUP */:
- case "reauthViaRedirect" /* AuthEventType.REAUTH_VIA_REDIRECT */:
- return _reauth;
- default:
- _fail(this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }
- }
- resolve(cred) {
- debugAssert(this.pendingPromise, 'Pending promise was never set');
- this.pendingPromise.resolve(cred);
- this.unregisterAndCleanUp();
- }
- reject(error) {
- debugAssert(this.pendingPromise, 'Pending promise was never set');
- this.pendingPromise.reject(error);
- this.unregisterAndCleanUp();
- }
- unregisterAndCleanUp() {
- if (this.eventManager) {
- this.eventManager.unregisterConsumer(this);
- }
- this.pendingPromise = null;
- this.cleanUp();
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const _POLL_WINDOW_CLOSE_TIMEOUT = new Delay(2000, 10000);
- /**
- * Authenticates a Firebase client using a popup-based OAuth authentication flow.
- *
- * @remarks
- * If succeeds, returns the signed in user along with the provider's credential. If sign in was
- * unsuccessful, returns an error object containing additional information about the error.
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new FacebookAuthProvider();
- * const result = await signInWithPopup(auth, provider);
- *
- * // The signed-in user info.
- * const user = result.user;
- * // This gives you a Facebook Access Token.
- * const credential = provider.credentialFromResult(auth, result);
- * const token = credential.accessToken;
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- *
- * @public
- */
- async function signInWithPopup(auth, provider, resolver) {
- const authInternal = _castAuth(auth);
- _assertInstanceOf(auth, provider, FederatedAuthProvider);
- const resolverInternal = _withDefaultResolver(authInternal, resolver);
- const action = new PopupOperation(authInternal, "signInViaPopup" /* AuthEventType.SIGN_IN_VIA_POPUP */, provider, resolverInternal);
- return action.executeNotNull();
- }
- /**
- * Reauthenticates the current user with the specified {@link OAuthProvider} using a pop-up based
- * OAuth flow.
- *
- * @remarks
- * If the reauthentication is successful, the returned result will contain the user and the
- * provider's credential.
- *
- * @example
- * ```javascript
- * // Sign in using a popup.
- * const provider = new FacebookAuthProvider();
- * const result = await signInWithPopup(auth, provider);
- * // Reauthenticate using a popup.
- * await reauthenticateWithPopup(result.user, provider);
- * ```
- *
- * @param user - The user.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- * @public
- */
- async function reauthenticateWithPopup(user, provider, resolver) {
- const userInternal = getModularInstance(user);
- _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);
- const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
- const action = new PopupOperation(userInternal.auth, "reauthViaPopup" /* AuthEventType.REAUTH_VIA_POPUP */, provider, resolverInternal, userInternal);
- return action.executeNotNull();
- }
- /**
- * Links the authenticated provider to the user account using a pop-up based OAuth flow.
- *
- * @remarks
- * If the linking is successful, the returned result will contain the user and the provider's credential.
- *
- *
- * @example
- * ```javascript
- * // Sign in using some other provider.
- * const result = await signInWithEmailAndPassword(auth, email, password);
- * // Link using a popup.
- * const provider = new FacebookAuthProvider();
- * await linkWithPopup(result.user, provider);
- * ```
- *
- * @param user - The user.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- * @public
- */
- async function linkWithPopup(user, provider, resolver) {
- const userInternal = getModularInstance(user);
- _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);
- const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
- const action = new PopupOperation(userInternal.auth, "linkViaPopup" /* AuthEventType.LINK_VIA_POPUP */, provider, resolverInternal, userInternal);
- return action.executeNotNull();
- }
- /**
- * Popup event manager. Handles the popup's entire lifecycle; listens to auth
- * events
- *
- */
- class PopupOperation extends AbstractPopupRedirectOperation {
- constructor(auth, filter, provider, resolver, user) {
- super(auth, filter, resolver, user);
- this.provider = provider;
- this.authWindow = null;
- this.pollId = null;
- if (PopupOperation.currentPopupAction) {
- PopupOperation.currentPopupAction.cancel();
- }
- PopupOperation.currentPopupAction = this;
- }
- async executeNotNull() {
- const result = await this.execute();
- _assert$4(result, this.auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return result;
- }
- async onExecution() {
- debugAssert(this.filter.length === 1, 'Popup operations only handle one event');
- const eventId = _generateEventId();
- this.authWindow = await this.resolver._openPopup(this.auth, this.provider, this.filter[0], // There's always one, see constructor
- eventId);
- this.authWindow.associatedEvent = eventId;
- // Check for web storage support and origin validation _after_ the popup is
- // loaded. These operations are slow (~1 second or so) Rather than
- // waiting on them before opening the window, optimistically open the popup
- // and check for storage support at the same time. If storage support is
- // not available, this will cause the whole thing to reject properly. It
- // will also close the popup, but since the promise has already rejected,
- // the popup closed by user poll will reject into the void.
- this.resolver._originValidation(this.auth).catch(e => {
- this.reject(e);
- });
- this.resolver._isIframeWebStorageSupported(this.auth, isSupported => {
- if (!isSupported) {
- this.reject(_createError(this.auth, "web-storage-unsupported" /* AuthErrorCode.WEB_STORAGE_UNSUPPORTED */));
- }
- });
- // Handle user closure. Notice this does *not* use await
- this.pollUserCancellation();
- }
- get eventId() {
- var _a;
- return ((_a = this.authWindow) === null || _a === void 0 ? void 0 : _a.associatedEvent) || null;
- }
- cancel() {
- this.reject(_createError(this.auth, "cancelled-popup-request" /* AuthErrorCode.EXPIRED_POPUP_REQUEST */));
- }
- cleanUp() {
- if (this.authWindow) {
- this.authWindow.close();
- }
- if (this.pollId) {
- window.clearTimeout(this.pollId);
- }
- this.authWindow = null;
- this.pollId = null;
- PopupOperation.currentPopupAction = null;
- }
- pollUserCancellation() {
- const poll = () => {
- var _a, _b;
- if ((_b = (_a = this.authWindow) === null || _a === void 0 ? void 0 : _a.window) === null || _b === void 0 ? void 0 : _b.closed) {
- // Make sure that there is sufficient time for whatever action to
- // complete. The window could have closed but the sign in network
- // call could still be in flight. This is specifically true for
- // Firefox or if the opener is in an iframe, in which case the oauth
- // helper closes the popup.
- this.pollId = window.setTimeout(() => {
- this.pollId = null;
- this.reject(_createError(this.auth, "popup-closed-by-user" /* AuthErrorCode.POPUP_CLOSED_BY_USER */));
- }, 8000 /* _Timeout.AUTH_EVENT */);
- return;
- }
- this.pollId = window.setTimeout(poll, _POLL_WINDOW_CLOSE_TIMEOUT.get());
- };
- poll();
- }
- }
- // Only one popup is ever shown at once. The lifecycle of the current popup
- // can be managed / cancelled by the constructor.
- PopupOperation.currentPopupAction = null;
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const PENDING_REDIRECT_KEY = 'pendingRedirect';
- // We only get one redirect outcome for any one auth, so just store it
- // in here.
- const redirectOutcomeMap = new Map();
- class RedirectAction extends AbstractPopupRedirectOperation {
- constructor(auth, resolver, bypassAuthState = false) {
- super(auth, [
- "signInViaRedirect" /* AuthEventType.SIGN_IN_VIA_REDIRECT */,
- "linkViaRedirect" /* AuthEventType.LINK_VIA_REDIRECT */,
- "reauthViaRedirect" /* AuthEventType.REAUTH_VIA_REDIRECT */,
- "unknown" /* AuthEventType.UNKNOWN */
- ], resolver, undefined, bypassAuthState);
- this.eventId = null;
- }
- /**
- * Override the execute function; if we already have a redirect result, then
- * just return it.
- */
- async execute() {
- let readyOutcome = redirectOutcomeMap.get(this.auth._key());
- if (!readyOutcome) {
- try {
- const hasPendingRedirect = await _getAndClearPendingRedirectStatus(this.resolver, this.auth);
- const result = hasPendingRedirect ? await super.execute() : null;
- readyOutcome = () => Promise.resolve(result);
- }
- catch (e) {
- readyOutcome = () => Promise.reject(e);
- }
- redirectOutcomeMap.set(this.auth._key(), readyOutcome);
- }
- // If we're not bypassing auth state, the ready outcome should be set to
- // null.
- if (!this.bypassAuthState) {
- redirectOutcomeMap.set(this.auth._key(), () => Promise.resolve(null));
- }
- return readyOutcome();
- }
- async onAuthEvent(event) {
- if (event.type === "signInViaRedirect" /* AuthEventType.SIGN_IN_VIA_REDIRECT */) {
- return super.onAuthEvent(event);
- }
- else if (event.type === "unknown" /* AuthEventType.UNKNOWN */) {
- // This is a sentinel value indicating there's no pending redirect
- this.resolve(null);
- return;
- }
- if (event.eventId) {
- const user = await this.auth._redirectUserForId(event.eventId);
- if (user) {
- this.user = user;
- return super.onAuthEvent(event);
- }
- else {
- this.resolve(null);
- }
- }
- }
- async onExecution() { }
- cleanUp() { }
- }
- async function _getAndClearPendingRedirectStatus(resolver, auth) {
- const key = pendingRedirectKey(auth);
- const persistence = resolverPersistence(resolver);
- if (!(await persistence._isAvailable())) {
- return false;
- }
- const hasPendingRedirect = (await persistence._get(key)) === 'true';
- await persistence._remove(key);
- return hasPendingRedirect;
- }
- async function _setPendingRedirectStatus(resolver, auth) {
- return resolverPersistence(resolver)._set(pendingRedirectKey(auth), 'true');
- }
- function _clearRedirectOutcomes() {
- redirectOutcomeMap.clear();
- }
- function _overrideRedirectResult(auth, result) {
- redirectOutcomeMap.set(auth._key(), result);
- }
- function resolverPersistence(resolver) {
- return _getInstance(resolver._redirectPersistence);
- }
- function pendingRedirectKey(auth) {
- return _persistenceKeyName(PENDING_REDIRECT_KEY, auth.config.apiKey, auth.name);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * Authenticates a Firebase client using a full-page redirect flow.
- *
- * @remarks
- * To handle the results and errors for this operation, refer to {@link getRedirectResult}.
- * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices
- * | best practices} when using {@link signInWithRedirect}.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new FacebookAuthProvider();
- * // You can add additional scopes to the provider:
- * provider.addScope('user_birthday');
- * // Start a sign in process for an unauthenticated user.
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Facebook Access Token.
- * const credential = provider.credentialFromResult(auth, result);
- * const token = credential.accessToken;
- * }
- * // As this API can be used for sign-in, linking and reauthentication,
- * // check the operationType to determine what triggered this redirect
- * // operation.
- * const operationType = result.operationType;
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- * @public
- */
- function signInWithRedirect(auth, provider, resolver) {
- return _signInWithRedirect(auth, provider, resolver);
- }
- async function _signInWithRedirect(auth, provider, resolver) {
- const authInternal = _castAuth(auth);
- _assertInstanceOf(auth, provider, FederatedAuthProvider);
- // Wait for auth initialization to complete, this will process pending redirects and clear the
- // PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
- // redirect and creating a PENDING_REDIRECT_KEY entry.
- await authInternal._initializationPromise;
- const resolverInternal = _withDefaultResolver(authInternal, resolver);
- await _setPendingRedirectStatus(resolverInternal, authInternal);
- return resolverInternal._openRedirect(authInternal, provider, "signInViaRedirect" /* AuthEventType.SIGN_IN_VIA_REDIRECT */);
- }
- /**
- * Reauthenticates the current user with the specified {@link OAuthProvider} using a full-page redirect flow.
- * @remarks
- * To handle the results and errors for this operation, refer to {@link getRedirectResult}.
- * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices
- * | best practices} when using {@link reauthenticateWithRedirect}.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new FacebookAuthProvider();
- * const result = await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * // Reauthenticate using a redirect.
- * await reauthenticateWithRedirect(result.user, provider);
- * // This will again trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * ```
- *
- * @param user - The user.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- * @public
- */
- function reauthenticateWithRedirect(user, provider, resolver) {
- return _reauthenticateWithRedirect(user, provider, resolver);
- }
- async function _reauthenticateWithRedirect(user, provider, resolver) {
- const userInternal = getModularInstance(user);
- _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);
- // Wait for auth initialization to complete, this will process pending redirects and clear the
- // PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
- // redirect and creating a PENDING_REDIRECT_KEY entry.
- await userInternal.auth._initializationPromise;
- // Allow the resolver to error before persisting the redirect user
- const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
- await _setPendingRedirectStatus(resolverInternal, userInternal.auth);
- const eventId = await prepareUserForRedirect(userInternal);
- return resolverInternal._openRedirect(userInternal.auth, provider, "reauthViaRedirect" /* AuthEventType.REAUTH_VIA_REDIRECT */, eventId);
- }
- /**
- * Links the {@link OAuthProvider} to the user account using a full-page redirect flow.
- * @remarks
- * To handle the results and errors for this operation, refer to {@link getRedirectResult}.
- * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices
- * | best practices} when using {@link linkWithRedirect}.
- *
- * @example
- * ```javascript
- * // Sign in using some other provider.
- * const result = await signInWithEmailAndPassword(auth, email, password);
- * // Link using a redirect.
- * const provider = new FacebookAuthProvider();
- * await linkWithRedirect(result.user, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * ```
- *
- * @param user - The user.
- * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}.
- * Non-OAuth providers like {@link EmailAuthProvider} will throw an error.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- *
- * @public
- */
- function linkWithRedirect(user, provider, resolver) {
- return _linkWithRedirect(user, provider, resolver);
- }
- async function _linkWithRedirect(user, provider, resolver) {
- const userInternal = getModularInstance(user);
- _assertInstanceOf(userInternal.auth, provider, FederatedAuthProvider);
- // Wait for auth initialization to complete, this will process pending redirects and clear the
- // PENDING_REDIRECT_KEY in persistence. This should be completed before starting a new
- // redirect and creating a PENDING_REDIRECT_KEY entry.
- await userInternal.auth._initializationPromise;
- // Allow the resolver to error before persisting the redirect user
- const resolverInternal = _withDefaultResolver(userInternal.auth, resolver);
- await _assertLinkedStatus(false, userInternal, provider.providerId);
- await _setPendingRedirectStatus(resolverInternal, userInternal.auth);
- const eventId = await prepareUserForRedirect(userInternal);
- return resolverInternal._openRedirect(userInternal.auth, provider, "linkViaRedirect" /* AuthEventType.LINK_VIA_REDIRECT */, eventId);
- }
- /**
- * Returns a {@link UserCredential} from the redirect-based sign-in flow.
- *
- * @remarks
- * If sign-in succeeded, returns the signed in user. If sign-in was unsuccessful, fails with an
- * error. If no redirect operation was called, returns `null`.
- *
- * @example
- * ```javascript
- * // Sign in using a redirect.
- * const provider = new FacebookAuthProvider();
- * // You can add additional scopes to the provider:
- * provider.addScope('user_birthday');
- * // Start a sign in process for an unauthenticated user.
- * await signInWithRedirect(auth, provider);
- * // This will trigger a full page redirect away from your app
- *
- * // After returning from the redirect when your app initializes you can obtain the result
- * const result = await getRedirectResult(auth);
- * if (result) {
- * // This is the signed-in user
- * const user = result.user;
- * // This gives you a Facebook Access Token.
- * const credential = provider.credentialFromResult(auth, result);
- * const token = credential.accessToken;
- * }
- * // As this API can be used for sign-in, linking and reauthentication,
- * // check the operationType to determine what triggered this redirect
- * // operation.
- * const operationType = result.operationType;
- * ```
- *
- * @param auth - The {@link Auth} instance.
- * @param resolver - An instance of {@link PopupRedirectResolver}, optional
- * if already supplied to {@link initializeAuth} or provided by {@link getAuth}.
- *
- * @public
- */
- async function getRedirectResult(auth, resolver) {
- await _castAuth(auth)._initializationPromise;
- return _getRedirectResult(auth, resolver, false);
- }
- async function _getRedirectResult(auth, resolverExtern, bypassAuthState = false) {
- const authInternal = _castAuth(auth);
- const resolver = _withDefaultResolver(authInternal, resolverExtern);
- const action = new RedirectAction(authInternal, resolver, bypassAuthState);
- const result = await action.execute();
- if (result && !bypassAuthState) {
- delete result.user._redirectEventId;
- await authInternal._persistUserIfCurrent(result.user);
- await authInternal._setRedirectUser(null, resolverExtern);
- }
- return result;
- }
- async function prepareUserForRedirect(user) {
- const eventId = _generateEventId(`${user.uid}:::`);
- user._redirectEventId = eventId;
- await user.auth._setRedirectUser(user);
- await user.auth._persistUserIfCurrent(user);
- return eventId;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // The amount of time to store the UIDs of seen events; this is
- // set to 10 min by default
- const EVENT_DUPLICATION_CACHE_DURATION_MS = 10 * 60 * 1000;
- class AuthEventManager {
- constructor(auth) {
- this.auth = auth;
- this.cachedEventUids = new Set();
- this.consumers = new Set();
- this.queuedRedirectEvent = null;
- this.hasHandledPotentialRedirect = false;
- this.lastProcessedEventTime = Date.now();
- }
- registerConsumer(authEventConsumer) {
- this.consumers.add(authEventConsumer);
- if (this.queuedRedirectEvent &&
- this.isEventForConsumer(this.queuedRedirectEvent, authEventConsumer)) {
- this.sendToConsumer(this.queuedRedirectEvent, authEventConsumer);
- this.saveEventToCache(this.queuedRedirectEvent);
- this.queuedRedirectEvent = null;
- }
- }
- unregisterConsumer(authEventConsumer) {
- this.consumers.delete(authEventConsumer);
- }
- onEvent(event) {
- // Check if the event has already been handled
- if (this.hasEventBeenHandled(event)) {
- return false;
- }
- let handled = false;
- this.consumers.forEach(consumer => {
- if (this.isEventForConsumer(event, consumer)) {
- handled = true;
- this.sendToConsumer(event, consumer);
- this.saveEventToCache(event);
- }
- });
- if (this.hasHandledPotentialRedirect || !isRedirectEvent(event)) {
- // If we've already seen a redirect before, or this is a popup event,
- // bail now
- return handled;
- }
- this.hasHandledPotentialRedirect = true;
- // If the redirect wasn't handled, hang on to it
- if (!handled) {
- this.queuedRedirectEvent = event;
- handled = true;
- }
- return handled;
- }
- sendToConsumer(event, consumer) {
- var _a;
- if (event.error && !isNullRedirectEvent(event)) {
- const code = ((_a = event.error.code) === null || _a === void 0 ? void 0 : _a.split('auth/')[1]) ||
- "internal-error" /* AuthErrorCode.INTERNAL_ERROR */;
- consumer.onError(_createError(this.auth, code));
- }
- else {
- consumer.onAuthEvent(event);
- }
- }
- isEventForConsumer(event, consumer) {
- const eventIdMatches = consumer.eventId === null ||
- (!!event.eventId && event.eventId === consumer.eventId);
- return consumer.filter.includes(event.type) && eventIdMatches;
- }
- hasEventBeenHandled(event) {
- if (Date.now() - this.lastProcessedEventTime >=
- EVENT_DUPLICATION_CACHE_DURATION_MS) {
- this.cachedEventUids.clear();
- }
- return this.cachedEventUids.has(eventUid(event));
- }
- saveEventToCache(event) {
- this.cachedEventUids.add(eventUid(event));
- this.lastProcessedEventTime = Date.now();
- }
- }
- function eventUid(e) {
- return [e.type, e.eventId, e.sessionId, e.tenantId].filter(v => v).join('-');
- }
- function isNullRedirectEvent({ type, error }) {
- return (type === "unknown" /* AuthEventType.UNKNOWN */ &&
- (error === null || error === void 0 ? void 0 : error.code) === `auth/${"no-auth-event" /* AuthErrorCode.NO_AUTH_EVENT */}`);
- }
- function isRedirectEvent(event) {
- switch (event.type) {
- case "signInViaRedirect" /* AuthEventType.SIGN_IN_VIA_REDIRECT */:
- case "linkViaRedirect" /* AuthEventType.LINK_VIA_REDIRECT */:
- case "reauthViaRedirect" /* AuthEventType.REAUTH_VIA_REDIRECT */:
- return true;
- case "unknown" /* AuthEventType.UNKNOWN */:
- return isNullRedirectEvent(event);
- default:
- return false;
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- async function _getProjectConfig(auth, request = {}) {
- return _performApiRequest(auth, "GET" /* HttpMethod.GET */, "/v1/projects" /* Endpoint.GET_PROJECT_CONFIG */, request);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const IP_ADDRESS_REGEX = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
- const HTTP_REGEX = /^https?/;
- async function _validateOrigin$1(auth) {
- // Skip origin validation if we are in an emulated environment
- if (auth.config.emulator) {
- return;
- }
- const { authorizedDomains } = await _getProjectConfig(auth);
- for (const domain of authorizedDomains) {
- try {
- if (matchDomain(domain)) {
- return;
- }
- }
- catch (_a) {
- // Do nothing if there's a URL error; just continue searching
- }
- }
- // In the old SDK, this error also provides helpful messages.
- _fail(auth, "unauthorized-domain" /* AuthErrorCode.INVALID_ORIGIN */);
- }
- function matchDomain(expected) {
- const currentUrl = _getCurrentUrl();
- const { protocol, hostname } = new URL(currentUrl);
- if (expected.startsWith('chrome-extension://')) {
- const ceUrl = new URL(expected);
- if (ceUrl.hostname === '' && hostname === '') {
- // For some reason we're not parsing chrome URLs properly
- return (protocol === 'chrome-extension:' &&
- expected.replace('chrome-extension://', '') ===
- currentUrl.replace('chrome-extension://', ''));
- }
- return protocol === 'chrome-extension:' && ceUrl.hostname === hostname;
- }
- if (!HTTP_REGEX.test(protocol)) {
- return false;
- }
- if (IP_ADDRESS_REGEX.test(expected)) {
- // The domain has to be exactly equal to the pattern, as an IP domain will
- // only contain the IP, no extra character.
- return hostname === expected;
- }
- // Dots in pattern should be escaped.
- const escapedDomainPattern = expected.replace(/\./g, '\\.');
- // Non ip address domains.
- // domain.com = *.domain.com OR domain.com
- const re = new RegExp('^(.+\\.' + escapedDomainPattern + '|' + escapedDomainPattern + ')$', 'i');
- return re.test(hostname);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const NETWORK_TIMEOUT = new Delay(30000, 60000);
- /**
- * Reset unlaoded GApi modules. If gapi.load fails due to a network error,
- * it will stop working after a retrial. This is a hack to fix this issue.
- */
- function resetUnloadedGapiModules() {
- // Clear last failed gapi.load state to force next gapi.load to first
- // load the failed gapi.iframes module.
- // Get gapix.beacon context.
- const beacon = _window().___jsl;
- // Get current hint.
- if (beacon === null || beacon === void 0 ? void 0 : beacon.H) {
- // Get gapi hint.
- for (const hint of Object.keys(beacon.H)) {
- // Requested modules.
- beacon.H[hint].r = beacon.H[hint].r || [];
- // Loaded modules.
- beacon.H[hint].L = beacon.H[hint].L || [];
- // Set requested modules to a copy of the loaded modules.
- beacon.H[hint].r = [...beacon.H[hint].L];
- // Clear pending callbacks.
- if (beacon.CP) {
- for (let i = 0; i < beacon.CP.length; i++) {
- // Remove all failed pending callbacks.
- beacon.CP[i] = null;
- }
- }
- }
- }
- }
- function loadGapi(auth) {
- return new Promise((resolve, reject) => {
- var _a, _b, _c;
- // Function to run when gapi.load is ready.
- function loadGapiIframe() {
- // The developer may have tried to previously run gapi.load and failed.
- // Run this to fix that.
- resetUnloadedGapiModules();
- gapi.load('gapi.iframes', {
- callback: () => {
- resolve(gapi.iframes.getContext());
- },
- ontimeout: () => {
- // The above reset may be sufficient, but having this reset after
- // failure ensures that if the developer calls gapi.load after the
- // connection is re-established and before another attempt to embed
- // the iframe, it would work and would not be broken because of our
- // failed attempt.
- // Timeout when gapi.iframes.Iframe not loaded.
- resetUnloadedGapiModules();
- reject(_createError(auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */));
- },
- timeout: NETWORK_TIMEOUT.get()
- });
- }
- if ((_b = (_a = _window().gapi) === null || _a === void 0 ? void 0 : _a.iframes) === null || _b === void 0 ? void 0 : _b.Iframe) {
- // If gapi.iframes.Iframe available, resolve.
- resolve(gapi.iframes.getContext());
- }
- else if (!!((_c = _window().gapi) === null || _c === void 0 ? void 0 : _c.load)) {
- // Gapi loader ready, load gapi.iframes.
- loadGapiIframe();
- }
- else {
- // Create a new iframe callback when this is called so as not to overwrite
- // any previous defined callback. This happens if this method is called
- // multiple times in parallel and could result in the later callback
- // overwriting the previous one. This would end up with a iframe
- // timeout.
- const cbName = _generateCallbackName('iframefcb');
- // GApi loader not available, dynamically load platform.js.
- _window()[cbName] = () => {
- // GApi loader should be ready.
- if (!!gapi.load) {
- loadGapiIframe();
- }
- else {
- // Gapi loader failed, throw error.
- reject(_createError(auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */));
- }
- };
- // Load GApi loader.
- return _loadJS(`https://apis.google.com/js/api.js?onload=${cbName}`)
- .catch(e => reject(e));
- }
- }).catch(error => {
- // Reset cached promise to allow for retrial.
- cachedGApiLoader = null;
- throw error;
- });
- }
- let cachedGApiLoader = null;
- function _loadGapi(auth) {
- cachedGApiLoader = cachedGApiLoader || loadGapi(auth);
- return cachedGApiLoader;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const PING_TIMEOUT = new Delay(5000, 15000);
- const IFRAME_PATH = '__/auth/iframe';
- const EMULATED_IFRAME_PATH = 'emulator/auth/iframe';
- const IFRAME_ATTRIBUTES = {
- style: {
- position: 'absolute',
- top: '-100px',
- width: '1px',
- height: '1px'
- },
- 'aria-hidden': 'true',
- tabindex: '-1'
- };
- // Map from apiHost to endpoint ID for passing into iframe. In current SDK, apiHost can be set to
- // anything (not from a list of endpoints with IDs as in legacy), so this is the closest we can get.
- const EID_FROM_APIHOST = new Map([
- ["identitytoolkit.googleapis.com" /* DefaultConfig.API_HOST */, 'p'],
- ['staging-identitytoolkit.sandbox.googleapis.com', 's'],
- ['test-identitytoolkit.sandbox.googleapis.com', 't'] // test
- ]);
- function getIframeUrl(auth) {
- const config = auth.config;
- _assert$4(config.authDomain, auth, "auth-domain-config-required" /* AuthErrorCode.MISSING_AUTH_DOMAIN */);
- const url = config.emulator
- ? _emulatorUrl(config, EMULATED_IFRAME_PATH)
- : `https://${auth.config.authDomain}/${IFRAME_PATH}`;
- const params = {
- apiKey: config.apiKey,
- appName: auth.name,
- v: SDK_VERSION$1
- };
- const eid = EID_FROM_APIHOST.get(auth.config.apiHost);
- if (eid) {
- params.eid = eid;
- }
- const frameworks = auth._getFrameworks();
- if (frameworks.length) {
- params.fw = frameworks.join(',');
- }
- return `${url}?${querystring(params).slice(1)}`;
- }
- async function _openIframe(auth) {
- const context = await _loadGapi(auth);
- const gapi = _window().gapi;
- _assert$4(gapi, auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- return context.open({
- where: document.body,
- url: getIframeUrl(auth),
- messageHandlersFilter: gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER,
- attributes: IFRAME_ATTRIBUTES,
- dontclear: true
- }, (iframe) => new Promise(async (resolve, reject) => {
- await iframe.restyle({
- // Prevent iframe from closing on mouse out.
- setHideOnLeave: false
- });
- const networkError = _createError(auth, "network-request-failed" /* AuthErrorCode.NETWORK_REQUEST_FAILED */);
- // Confirm iframe is correctly loaded.
- // To fallback on failure, set a timeout.
- const networkErrorTimer = _window().setTimeout(() => {
- reject(networkError);
- }, PING_TIMEOUT.get());
- // Clear timer and resolve pending iframe ready promise.
- function clearTimerAndResolve() {
- _window().clearTimeout(networkErrorTimer);
- resolve(iframe);
- }
- // This returns an IThenable. However the reject part does not call
- // when the iframe is not loaded.
- iframe.ping(clearTimerAndResolve).then(clearTimerAndResolve, () => {
- reject(networkError);
- });
- }));
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const BASE_POPUP_OPTIONS = {
- location: 'yes',
- resizable: 'yes',
- statusbar: 'yes',
- toolbar: 'no'
- };
- const DEFAULT_WIDTH = 500;
- const DEFAULT_HEIGHT = 600;
- const TARGET_BLANK = '_blank';
- const FIREFOX_EMPTY_URL = 'http://localhost';
- class AuthPopup {
- constructor(window) {
- this.window = window;
- this.associatedEvent = null;
- }
- close() {
- if (this.window) {
- try {
- this.window.close();
- }
- catch (e) { }
- }
- }
- }
- function _open(auth, url, name, width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT) {
- const top = Math.max((window.screen.availHeight - height) / 2, 0).toString();
- const left = Math.max((window.screen.availWidth - width) / 2, 0).toString();
- let target = '';
- const options = Object.assign(Object.assign({}, BASE_POPUP_OPTIONS), { width: width.toString(), height: height.toString(), top,
- left });
- // Chrome iOS 7 and 8 is returning an undefined popup win when target is
- // specified, even though the popup is not necessarily blocked.
- const ua = getUA().toLowerCase();
- if (name) {
- target = _isChromeIOS(ua) ? TARGET_BLANK : name;
- }
- if (_isFirefox(ua)) {
- // Firefox complains when invalid URLs are popped out. Hacky way to bypass.
- url = url || FIREFOX_EMPTY_URL;
- // Firefox disables by default scrolling on popup windows, which can create
- // issues when the user has many Google accounts, for instance.
- options.scrollbars = 'yes';
- }
- const optionsString = Object.entries(options).reduce((accum, [key, value]) => `${accum}${key}=${value},`, '');
- if (_isIOSStandalone(ua) && target !== '_self') {
- openAsNewWindowIOS(url || '', target);
- return new AuthPopup(null);
- }
- // about:blank getting sanitized causing browsers like IE/Edge to display
- // brief error message before redirecting to handler.
- const newWin = window.open(url || '', target, optionsString);
- _assert$4(newWin, auth, "popup-blocked" /* AuthErrorCode.POPUP_BLOCKED */);
- // Flaky on IE edge, encapsulate with a try and catch.
- try {
- newWin.focus();
- }
- catch (e) { }
- return new AuthPopup(newWin);
- }
- function openAsNewWindowIOS(url, target) {
- const el = document.createElement('a');
- el.href = url;
- el.target = target;
- const click = document.createEvent('MouseEvent');
- click.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 1, null);
- el.dispatchEvent(click);
- }
-
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * URL for Authentication widget which will initiate the OAuth handshake
- *
- * @internal
- */
- const WIDGET_PATH = '__/auth/handler';
- /**
- * URL for emulated environment
- *
- * @internal
- */
- const EMULATOR_WIDGET_PATH = 'emulator/auth/handler';
- /**
- * Fragment name for the App Check token that gets passed to the widget
- *
- * @internal
- */
- const FIREBASE_APP_CHECK_FRAGMENT_ID = encodeURIComponent('fac');
- async function _getRedirectUrl(auth, provider, authType, redirectUrl, eventId, additionalParams) {
- _assert$4(auth.config.authDomain, auth, "auth-domain-config-required" /* AuthErrorCode.MISSING_AUTH_DOMAIN */);
- _assert$4(auth.config.apiKey, auth, "invalid-api-key" /* AuthErrorCode.INVALID_API_KEY */);
- const params = {
- apiKey: auth.config.apiKey,
- appName: auth.name,
- authType,
- redirectUrl,
- v: SDK_VERSION$1,
- eventId
- };
- if (provider instanceof FederatedAuthProvider) {
- provider.setDefaultLanguage(auth.languageCode);
- params.providerId = provider.providerId || '';
- if (!isEmpty(provider.getCustomParameters())) {
- params.customParameters = JSON.stringify(provider.getCustomParameters());
- }
- // TODO set additionalParams from the provider as well?
- for (const [key, value] of Object.entries(additionalParams || {})) {
- params[key] = value;
- }
- }
- if (provider instanceof BaseOAuthProvider) {
- const scopes = provider.getScopes().filter(scope => scope !== '');
- if (scopes.length > 0) {
- params.scopes = scopes.join(',');
- }
- }
- if (auth.tenantId) {
- params.tid = auth.tenantId;
- }
- // TODO: maybe set eid as endipointId
- // TODO: maybe set fw as Frameworks.join(",")
- const paramsDict = params;
- for (const key of Object.keys(paramsDict)) {
- if (paramsDict[key] === undefined) {
- delete paramsDict[key];
- }
- }
- // Sets the App Check token to pass to the widget
- const appCheckToken = await auth._getAppCheckToken();
- const appCheckTokenFragment = appCheckToken
- ? `#${FIREBASE_APP_CHECK_FRAGMENT_ID}=${encodeURIComponent(appCheckToken)}`
- : '';
- // Start at index 1 to skip the leading '&' in the query string
- return `${getHandlerBase(auth)}?${querystring(paramsDict).slice(1)}${appCheckTokenFragment}`;
- }
- function getHandlerBase({ config }) {
- if (!config.emulator) {
- return `https://${config.authDomain}/${WIDGET_PATH}`;
- }
- return _emulatorUrl(config, EMULATOR_WIDGET_PATH);
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * The special web storage event
- *
- */
- const WEB_STORAGE_SUPPORT_KEY = 'webStorageSupport';
- class BrowserPopupRedirectResolver {
- constructor() {
- this.eventManagers = {};
- this.iframes = {};
- this.originValidationPromises = {};
- this._redirectPersistence = browserSessionPersistence;
- this._completeRedirectFn = _getRedirectResult;
- this._overrideRedirectResult = _overrideRedirectResult;
- }
- // Wrapping in async even though we don't await anywhere in order
- // to make sure errors are raised as promise rejections
- async _openPopup(auth, provider, authType, eventId) {
- var _a;
- debugAssert((_a = this.eventManagers[auth._key()]) === null || _a === void 0 ? void 0 : _a.manager, '_initialize() not called before _openPopup()');
- const url = await _getRedirectUrl(auth, provider, authType, _getCurrentUrl(), eventId);
- return _open(auth, url, _generateEventId());
- }
- async _openRedirect(auth, provider, authType, eventId) {
- await this._originValidation(auth);
- const url = await _getRedirectUrl(auth, provider, authType, _getCurrentUrl(), eventId);
- _setWindowLocation(url);
- return new Promise(() => { });
- }
- _initialize(auth) {
- const key = auth._key();
- if (this.eventManagers[key]) {
- const { manager, promise } = this.eventManagers[key];
- if (manager) {
- return Promise.resolve(manager);
- }
- else {
- debugAssert(promise, 'If manager is not set, promise should be');
- return promise;
- }
- }
- const promise = this.initAndGetManager(auth);
- this.eventManagers[key] = { promise };
- // If the promise is rejected, the key should be removed so that the
- // operation can be retried later.
- promise.catch(() => {
- delete this.eventManagers[key];
- });
- return promise;
- }
- async initAndGetManager(auth) {
- const iframe = await _openIframe(auth);
- const manager = new AuthEventManager(auth);
- iframe.register('authEvent', (iframeEvent) => {
- _assert$4(iframeEvent === null || iframeEvent === void 0 ? void 0 : iframeEvent.authEvent, auth, "invalid-auth-event" /* AuthErrorCode.INVALID_AUTH_EVENT */);
- // TODO: Consider splitting redirect and popup events earlier on
- const handled = manager.onEvent(iframeEvent.authEvent);
- return { status: handled ? "ACK" /* GapiOutcome.ACK */ : "ERROR" /* GapiOutcome.ERROR */ };
- }, gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER);
- this.eventManagers[auth._key()] = { manager };
- this.iframes[auth._key()] = iframe;
- return manager;
- }
- _isIframeWebStorageSupported(auth, cb) {
- const iframe = this.iframes[auth._key()];
- iframe.send(WEB_STORAGE_SUPPORT_KEY, { type: WEB_STORAGE_SUPPORT_KEY }, result => {
- var _a;
- const isSupported = (_a = result === null || result === void 0 ? void 0 : result[0]) === null || _a === void 0 ? void 0 : _a[WEB_STORAGE_SUPPORT_KEY];
- if (isSupported !== undefined) {
- cb(!!isSupported);
- }
- _fail(auth, "internal-error" /* AuthErrorCode.INTERNAL_ERROR */);
- }, gapi.iframes.CROSS_ORIGIN_IFRAMES_FILTER);
- }
- _originValidation(auth) {
- const key = auth._key();
- if (!this.originValidationPromises[key]) {
- this.originValidationPromises[key] = _validateOrigin$1(auth);
- }
- return this.originValidationPromises[key];
- }
- get _shouldInitProactively() {
- // Mobile browsers and Safari need to optimistically initialize
- return _isMobileBrowser() || _isSafari() || _isIOS();
- }
- }
- /**
- * An implementation of {@link PopupRedirectResolver} suitable for browser
- * based applications.
- *
- * @public
- */
- const browserPopupRedirectResolver = BrowserPopupRedirectResolver;
-
- class MultiFactorAssertionImpl {
- constructor(factorId) {
- this.factorId = factorId;
- }
- _process(auth, session, displayName) {
- switch (session.type) {
- case "enroll" /* MultiFactorSessionType.ENROLL */:
- return this._finalizeEnroll(auth, session.credential, displayName);
- case "signin" /* MultiFactorSessionType.SIGN_IN */:
- return this._finalizeSignIn(auth, session.credential);
- default:
- return debugFail('unexpected MultiFactorSessionType');
- }
- }
- }
-
- /**
- * {@inheritdoc PhoneMultiFactorAssertion}
- *
- * @public
- */
- class PhoneMultiFactorAssertionImpl extends MultiFactorAssertionImpl {
- constructor(credential) {
- super("phone" /* FactorId.PHONE */);
- this.credential = credential;
- }
- /** @internal */
- static _fromCredential(credential) {
- return new PhoneMultiFactorAssertionImpl(credential);
- }
- /** @internal */
- _finalizeEnroll(auth, idToken, displayName) {
- return finalizeEnrollPhoneMfa(auth, {
- idToken,
- displayName,
- phoneVerificationInfo: this.credential._makeVerificationRequest()
- });
- }
- /** @internal */
- _finalizeSignIn(auth, mfaPendingCredential) {
- return finalizeSignInPhoneMfa(auth, {
- mfaPendingCredential,
- phoneVerificationInfo: this.credential._makeVerificationRequest()
- });
- }
- }
- /**
- * Provider for generating a {@link PhoneMultiFactorAssertion}.
- *
- * @public
- */
- class PhoneMultiFactorGenerator {
- constructor() { }
- /**
- * Provides a {@link PhoneMultiFactorAssertion} to confirm ownership of the phone second factor.
- *
- * @param phoneAuthCredential - A credential provided by {@link PhoneAuthProvider.credential}.
- * @returns A {@link PhoneMultiFactorAssertion} which can be used with
- * {@link MultiFactorResolver.resolveSignIn}
- */
- static assertion(credential) {
- return PhoneMultiFactorAssertionImpl._fromCredential(credential);
- }
- }
- /**
- * The identifier of the phone second factor: `phone`.
- */
- PhoneMultiFactorGenerator.FACTOR_ID = 'phone';
-
- var name$2 = "@firebase/auth";
- var version$2 = "0.23.2";
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class AuthInterop {
- constructor(auth) {
- this.auth = auth;
- this.internalListeners = new Map();
- }
- getUid() {
- var _a;
- this.assertAuthConfigured();
- return ((_a = this.auth.currentUser) === null || _a === void 0 ? void 0 : _a.uid) || null;
- }
- async getToken(forceRefresh) {
- this.assertAuthConfigured();
- await this.auth._initializationPromise;
- if (!this.auth.currentUser) {
- return null;
- }
- const accessToken = await this.auth.currentUser.getIdToken(forceRefresh);
- return { accessToken };
- }
- addAuthTokenListener(listener) {
- this.assertAuthConfigured();
- if (this.internalListeners.has(listener)) {
- return;
- }
- const unsubscribe = this.auth.onIdTokenChanged(user => {
- listener((user === null || user === void 0 ? void 0 : user.stsTokenManager.accessToken) || null);
- });
- this.internalListeners.set(listener, unsubscribe);
- this.updateProactiveRefresh();
- }
- removeAuthTokenListener(listener) {
- this.assertAuthConfigured();
- const unsubscribe = this.internalListeners.get(listener);
- if (!unsubscribe) {
- return;
- }
- this.internalListeners.delete(listener);
- unsubscribe();
- this.updateProactiveRefresh();
- }
- assertAuthConfigured() {
- _assert$4(this.auth._initializationPromise, "dependent-sdk-initialized-before-auth" /* AuthErrorCode.DEPENDENT_SDK_INIT_BEFORE_AUTH */);
- }
- updateProactiveRefresh() {
- if (this.internalListeners.size > 0) {
- this.auth._startProactiveRefresh();
- }
- else {
- this.auth._stopProactiveRefresh();
- }
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function getVersionForPlatform(clientPlatform) {
- switch (clientPlatform) {
- case "Node" /* ClientPlatform.NODE */:
- return 'node';
- case "ReactNative" /* ClientPlatform.REACT_NATIVE */:
- return 'rn';
- case "Worker" /* ClientPlatform.WORKER */:
- return 'webworker';
- case "Cordova" /* ClientPlatform.CORDOVA */:
- return 'cordova';
- default:
- return undefined;
- }
- }
- /** @internal */
- function registerAuth(clientPlatform) {
- _registerComponent(new Component("auth" /* _ComponentName.AUTH */, (container, { options: deps }) => {
- const app = container.getProvider('app').getImmediate();
- const heartbeatServiceProvider = container.getProvider('heartbeat');
- const appCheckServiceProvider = container.getProvider('app-check-internal');
- const { apiKey, authDomain } = app.options;
- _assert$4(apiKey && !apiKey.includes(':'), "invalid-api-key" /* AuthErrorCode.INVALID_API_KEY */, { appName: app.name });
- const config = {
- apiKey,
- authDomain,
- clientPlatform,
- apiHost: "identitytoolkit.googleapis.com" /* DefaultConfig.API_HOST */,
- tokenApiHost: "securetoken.googleapis.com" /* DefaultConfig.TOKEN_API_HOST */,
- apiScheme: "https" /* DefaultConfig.API_SCHEME */,
- sdkClientVersion: _getClientVersion(clientPlatform)
- };
- const authInstance = new AuthImpl(app, heartbeatServiceProvider, appCheckServiceProvider, config);
- _initializeAuthInstance(authInstance, deps);
- return authInstance;
- }, "PUBLIC" /* ComponentType.PUBLIC */)
- /**
- * Auth can only be initialized by explicitly calling getAuth() or initializeAuth()
- * For why we do this, See go/firebase-next-auth-init
- */
- .setInstantiationMode("EXPLICIT" /* InstantiationMode.EXPLICIT */)
- /**
- * Because all firebase products that depend on auth depend on auth-internal directly,
- * we need to initialize auth-internal after auth is initialized to make it available to other firebase products.
- */
- .setInstanceCreatedCallback((container, _instanceIdentifier, _instance) => {
- const authInternalProvider = container.getProvider("auth-internal" /* _ComponentName.AUTH_INTERNAL */);
- authInternalProvider.initialize();
- }));
- _registerComponent(new Component("auth-internal" /* _ComponentName.AUTH_INTERNAL */, container => {
- const auth = _castAuth(container.getProvider("auth" /* _ComponentName.AUTH */).getImmediate());
- return (auth => new AuthInterop(auth))(auth);
- }, "PRIVATE" /* ComponentType.PRIVATE */).setInstantiationMode("EXPLICIT" /* InstantiationMode.EXPLICIT */));
- registerVersion(name$2, version$2, getVersionForPlatform(clientPlatform));
- // BUILD_TARGET will be replaced by values like esm5, esm2017, cjs5, etc during the compilation
- registerVersion(name$2, version$2, 'esm2017');
- }
-
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const DEFAULT_ID_TOKEN_MAX_AGE = 5 * 60;
- getExperimentalSetting('authIdTokenMaxAge') || DEFAULT_ID_TOKEN_MAX_AGE;
- registerAuth("Browser" /* ClientPlatform.BROWSER */);
-
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function _cordovaWindow() {
- return window;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * How long to wait after the app comes back into focus before concluding that
- * the user closed the sign in tab.
- */
- const REDIRECT_TIMEOUT_MS = 2000;
- /**
- * Generates the URL for the OAuth handler.
- */
- async function _generateHandlerUrl(auth, event, provider) {
- var _a;
- // Get the cordova plugins
- const { BuildInfo } = _cordovaWindow();
- debugAssert(event.sessionId, 'AuthEvent did not contain a session ID');
- const sessionDigest = await computeSha256(event.sessionId);
- const additionalParams = {};
- if (_isIOS()) {
- // iOS app identifier
- additionalParams['ibi'] = BuildInfo.packageName;
- }
- else if (_isAndroid()) {
- // Android app identifier
- additionalParams['apn'] = BuildInfo.packageName;
- }
- else {
- _fail(auth, "operation-not-supported-in-this-environment" /* AuthErrorCode.OPERATION_NOT_SUPPORTED */);
- }
- // Add the display name if available
- if (BuildInfo.displayName) {
- additionalParams['appDisplayName'] = BuildInfo.displayName;
- }
- // Attached the hashed session ID
- additionalParams['sessionId'] = sessionDigest;
- return _getRedirectUrl(auth, provider, event.type, undefined, (_a = event.eventId) !== null && _a !== void 0 ? _a : undefined, additionalParams);
- }
- /**
- * Validates that this app is valid for this project configuration
- */
- async function _validateOrigin(auth) {
- const { BuildInfo } = _cordovaWindow();
- const request = {};
- if (_isIOS()) {
- request.iosBundleId = BuildInfo.packageName;
- }
- else if (_isAndroid()) {
- request.androidPackageName = BuildInfo.packageName;
- }
- else {
- _fail(auth, "operation-not-supported-in-this-environment" /* AuthErrorCode.OPERATION_NOT_SUPPORTED */);
- }
- // Will fail automatically if package name is not authorized
- await _getProjectConfig(auth, request);
- }
- function _performRedirect(handlerUrl) {
- // Get the cordova plugins
- const { cordova } = _cordovaWindow();
- return new Promise(resolve => {
- cordova.plugins.browsertab.isAvailable(browserTabIsAvailable => {
- let iabRef = null;
- if (browserTabIsAvailable) {
- cordova.plugins.browsertab.openUrl(handlerUrl);
- }
- else {
- // TODO: Return the inappbrowser ref that's returned from the open call
- iabRef = cordova.InAppBrowser.open(handlerUrl, _isIOS7Or8() ? '_blank' : '_system', 'location=yes');
- }
- resolve(iabRef);
- });
- });
- }
- /**
- * This function waits for app activity to be seen before resolving. It does
- * this by attaching listeners to various dom events. Once the app is determined
- * to be visible, this promise resolves. AFTER that resolution, the listeners
- * are detached and any browser tabs left open will be closed.
- */
- async function _waitForAppResume(auth, eventListener, iabRef) {
- // Get the cordova plugins
- const { cordova } = _cordovaWindow();
- let cleanup = () => { };
- try {
- await new Promise((resolve, reject) => {
- let onCloseTimer = null;
- // DEFINE ALL THE CALLBACKS =====
- function authEventSeen() {
- var _a;
- // Auth event was detected. Resolve this promise and close the extra
- // window if it's still open.
- resolve();
- const closeBrowserTab = (_a = cordova.plugins.browsertab) === null || _a === void 0 ? void 0 : _a.close;
- if (typeof closeBrowserTab === 'function') {
- closeBrowserTab();
- }
- // Close inappbrowser emebedded webview in iOS7 and 8 case if still
- // open.
- if (typeof (iabRef === null || iabRef === void 0 ? void 0 : iabRef.close) === 'function') {
- iabRef.close();
- }
- }
- function resumed() {
- if (onCloseTimer) {
- // This code already ran; do not rerun.
- return;
- }
- onCloseTimer = window.setTimeout(() => {
- // Wait two seeconds after resume then reject.
- reject(_createError(auth, "redirect-cancelled-by-user" /* AuthErrorCode.REDIRECT_CANCELLED_BY_USER */));
- }, REDIRECT_TIMEOUT_MS);
- }
- function visibilityChanged() {
- if ((document === null || document === void 0 ? void 0 : document.visibilityState) === 'visible') {
- resumed();
- }
- }
- // ATTACH ALL THE LISTENERS =====
- // Listen for the auth event
- eventListener.addPassiveListener(authEventSeen);
- // Listen for resume and visibility events
- document.addEventListener('resume', resumed, false);
- if (_isAndroid()) {
- document.addEventListener('visibilitychange', visibilityChanged, false);
- }
- // SETUP THE CLEANUP FUNCTION =====
- cleanup = () => {
- eventListener.removePassiveListener(authEventSeen);
- document.removeEventListener('resume', resumed, false);
- document.removeEventListener('visibilitychange', visibilityChanged, false);
- if (onCloseTimer) {
- window.clearTimeout(onCloseTimer);
- }
- };
- });
- }
- finally {
- cleanup();
- }
- }
- /**
- * Checks the configuration of the Cordova environment. This has no side effect
- * if the configuration is correct; otherwise it throws an error with the
- * missing plugin.
- */
- function _checkCordovaConfiguration(auth) {
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
- const win = _cordovaWindow();
- // Check all dependencies installed.
- // https://github.com/nordnet/cordova-universal-links-plugin
- // Note that cordova-universal-links-plugin has been abandoned.
- // A fork with latest fixes is available at:
- // https://www.npmjs.com/package/cordova-universal-links-plugin-fix
- _assert$4(typeof ((_a = win === null || win === void 0 ? void 0 : win.universalLinks) === null || _a === void 0 ? void 0 : _a.subscribe) === 'function', auth, "invalid-cordova-configuration" /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */, {
- missingPlugin: 'cordova-universal-links-plugin-fix'
- });
- // https://www.npmjs.com/package/cordova-plugin-buildinfo
- _assert$4(typeof ((_b = win === null || win === void 0 ? void 0 : win.BuildInfo) === null || _b === void 0 ? void 0 : _b.packageName) !== 'undefined', auth, "invalid-cordova-configuration" /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */, {
- missingPlugin: 'cordova-plugin-buildInfo'
- });
- // https://github.com/google/cordova-plugin-browsertab
- _assert$4(typeof ((_e = (_d = (_c = win === null || win === void 0 ? void 0 : win.cordova) === null || _c === void 0 ? void 0 : _c.plugins) === null || _d === void 0 ? void 0 : _d.browsertab) === null || _e === void 0 ? void 0 : _e.openUrl) === 'function', auth, "invalid-cordova-configuration" /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */, {
- missingPlugin: 'cordova-plugin-browsertab'
- });
- _assert$4(typeof ((_h = (_g = (_f = win === null || win === void 0 ? void 0 : win.cordova) === null || _f === void 0 ? void 0 : _f.plugins) === null || _g === void 0 ? void 0 : _g.browsertab) === null || _h === void 0 ? void 0 : _h.isAvailable) === 'function', auth, "invalid-cordova-configuration" /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */, {
- missingPlugin: 'cordova-plugin-browsertab'
- });
- // https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/
- _assert$4(typeof ((_k = (_j = win === null || win === void 0 ? void 0 : win.cordova) === null || _j === void 0 ? void 0 : _j.InAppBrowser) === null || _k === void 0 ? void 0 : _k.open) === 'function', auth, "invalid-cordova-configuration" /* AuthErrorCode.INVALID_CORDOVA_CONFIGURATION */, {
- missingPlugin: 'cordova-plugin-inappbrowser'
- });
- }
- /**
- * Computes the SHA-256 of a session ID. The SubtleCrypto interface is only
- * available in "secure" contexts, which covers Cordova (which is served on a file
- * protocol).
- */
- async function computeSha256(sessionId) {
- const bytes = stringToArrayBuffer(sessionId);
- // TODO: For IE11 crypto has a different name and this operation comes back
- // as an object, not a promise. This is the old proposed standard that
- // is used by IE11:
- // https://www.w3.org/TR/2013/WD-WebCryptoAPI-20130108/#cryptooperation-interface
- const buf = await crypto.subtle.digest('SHA-256', bytes);
- const arr = Array.from(new Uint8Array(buf));
- return arr.map(num => num.toString(16).padStart(2, '0')).join('');
- }
- function stringToArrayBuffer(str) {
- // This function is only meant to deal with an ASCII charset and makes
- // certain simplifying assumptions.
- debugAssert(/[0-9a-zA-Z]+/.test(str), 'Can only convert alpha-numeric strings');
- if (typeof TextEncoder !== 'undefined') {
- return new TextEncoder().encode(str);
- }
- const buff = new ArrayBuffer(str.length);
- const view = new Uint8Array(buff);
- for (let i = 0; i < str.length; i++) {
- view[i] = str.charCodeAt(i);
- }
- return view;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const SESSION_ID_LENGTH = 20;
- /** Custom AuthEventManager that adds passive listeners to events */
- class CordovaAuthEventManager extends AuthEventManager {
- constructor() {
- super(...arguments);
- this.passiveListeners = new Set();
- this.initPromise = new Promise(resolve => {
- this.resolveInialized = resolve;
- });
- }
- addPassiveListener(cb) {
- this.passiveListeners.add(cb);
- }
- removePassiveListener(cb) {
- this.passiveListeners.delete(cb);
- }
- // In a Cordova environment, this manager can live through multiple redirect
- // operations
- resetRedirect() {
- this.queuedRedirectEvent = null;
- this.hasHandledPotentialRedirect = false;
- }
- /** Override the onEvent method */
- onEvent(event) {
- this.resolveInialized();
- this.passiveListeners.forEach(cb => cb(event));
- return super.onEvent(event);
- }
- async initialized() {
- await this.initPromise;
- }
- }
- /**
- * Generates a (partial) {@link AuthEvent}.
- */
- function _generateNewEvent(auth, type, eventId = null) {
- return {
- type,
- eventId,
- urlResponse: null,
- sessionId: generateSessionId(),
- postBody: null,
- tenantId: auth.tenantId,
- error: _createError(auth, "no-auth-event" /* AuthErrorCode.NO_AUTH_EVENT */)
- };
- }
- function _savePartialEvent(auth, event) {
- return storage()._set(persistenceKey(auth), event);
- }
- async function _getAndRemoveEvent(auth) {
- const event = (await storage()._get(persistenceKey(auth)));
- if (event) {
- await storage()._remove(persistenceKey(auth));
- }
- return event;
- }
- function _eventFromPartialAndUrl(partialEvent, url) {
- var _a, _b;
- // Parse the deep link within the dynamic link URL.
- const callbackUrl = _getDeepLinkFromCallback(url);
- // Confirm it is actually a callback URL.
- // Currently the universal link will be of this format:
- // https:///__/auth/callback
- // This is a fake URL but is not intended to take the user anywhere
- // and just redirect to the app.
- if (callbackUrl.includes('/__/auth/callback')) {
- // Check if there is an error in the URL.
- // This mechanism is also used to pass errors back to the app:
- // https:///__/auth/callback?firebaseError=
- const params = searchParamsOrEmpty(callbackUrl);
- // Get the error object corresponding to the stringified error if found.
- const errorObject = params['firebaseError']
- ? parseJsonOrNull(decodeURIComponent(params['firebaseError']))
- : null;
- const code = (_b = (_a = errorObject === null || errorObject === void 0 ? void 0 : errorObject['code']) === null || _a === void 0 ? void 0 : _a.split('auth/')) === null || _b === void 0 ? void 0 : _b[1];
- const error = code ? _createError(code) : null;
- if (error) {
- return {
- type: partialEvent.type,
- eventId: partialEvent.eventId,
- tenantId: partialEvent.tenantId,
- error,
- urlResponse: null,
- sessionId: null,
- postBody: null
- };
- }
- else {
- return {
- type: partialEvent.type,
- eventId: partialEvent.eventId,
- tenantId: partialEvent.tenantId,
- sessionId: partialEvent.sessionId,
- urlResponse: callbackUrl,
- postBody: null
- };
- }
- }
- return null;
- }
- function generateSessionId() {
- const chars = [];
- const allowedChars = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
- for (let i = 0; i < SESSION_ID_LENGTH; i++) {
- const idx = Math.floor(Math.random() * allowedChars.length);
- chars.push(allowedChars.charAt(idx));
- }
- return chars.join('');
- }
- function storage() {
- return _getInstance(browserLocalPersistence);
- }
- function persistenceKey(auth) {
- return _persistenceKeyName("authEvent" /* KeyName.AUTH_EVENT */, auth.config.apiKey, auth.name);
- }
- function parseJsonOrNull(json) {
- try {
- return JSON.parse(json);
- }
- catch (e) {
- return null;
- }
- }
- // Exported for testing
- function _getDeepLinkFromCallback(url) {
- const params = searchParamsOrEmpty(url);
- const link = params['link'] ? decodeURIComponent(params['link']) : undefined;
- // Double link case (automatic redirect)
- const doubleDeepLink = searchParamsOrEmpty(link)['link'];
- // iOS custom scheme links.
- const iOSDeepLink = params['deep_link_id']
- ? decodeURIComponent(params['deep_link_id'])
- : undefined;
- const iOSDoubleDeepLink = searchParamsOrEmpty(iOSDeepLink)['link'];
- return iOSDoubleDeepLink || iOSDeepLink || doubleDeepLink || link || url;
- }
- /**
- * Optimistically tries to get search params from a string, or else returns an
- * empty search params object.
- */
- function searchParamsOrEmpty(url) {
- if (!(url === null || url === void 0 ? void 0 : url.includes('?'))) {
- return {};
- }
- const [_, ...rest] = url.split('?');
- return querystringDecode(rest.join('?'));
- }
-
- /**
- * @license
- * Copyright 2021 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /**
- * How long to wait for the initial auth event before concluding no
- * redirect pending
- */
- const INITIAL_EVENT_TIMEOUT_MS = 500;
- class CordovaPopupRedirectResolver {
- constructor() {
- this._redirectPersistence = browserSessionPersistence;
- this._shouldInitProactively = true; // This is lightweight for Cordova
- this.eventManagers = new Map();
- this.originValidationPromises = {};
- this._completeRedirectFn = _getRedirectResult;
- this._overrideRedirectResult = _overrideRedirectResult;
- }
- async _initialize(auth) {
- const key = auth._key();
- let manager = this.eventManagers.get(key);
- if (!manager) {
- manager = new CordovaAuthEventManager(auth);
- this.eventManagers.set(key, manager);
- this.attachCallbackListeners(auth, manager);
- }
- return manager;
- }
- _openPopup(auth) {
- _fail(auth, "operation-not-supported-in-this-environment" /* AuthErrorCode.OPERATION_NOT_SUPPORTED */);
- }
- async _openRedirect(auth, provider, authType, eventId) {
- _checkCordovaConfiguration(auth);
- const manager = await this._initialize(auth);
- await manager.initialized();
- // Reset the persisted redirect states. This does not matter on Web where
- // the redirect always blows away application state entirely. On Cordova,
- // the app maintains control flow through the redirect.
- manager.resetRedirect();
- _clearRedirectOutcomes();
- await this._originValidation(auth);
- const event = _generateNewEvent(auth, authType, eventId);
- await _savePartialEvent(auth, event);
- const url = await _generateHandlerUrl(auth, event, provider);
- const iabRef = await _performRedirect(url);
- return _waitForAppResume(auth, manager, iabRef);
- }
- _isIframeWebStorageSupported(_auth, _cb) {
- throw new Error('Method not implemented.');
- }
- _originValidation(auth) {
- const key = auth._key();
- if (!this.originValidationPromises[key]) {
- this.originValidationPromises[key] = _validateOrigin(auth);
- }
- return this.originValidationPromises[key];
- }
- attachCallbackListeners(auth, manager) {
- // Get the global plugins
- const { universalLinks, handleOpenURL, BuildInfo } = _cordovaWindow();
- const noEventTimeout = setTimeout(async () => {
- // We didn't see that initial event. Clear any pending object and
- // dispatch no event
- await _getAndRemoveEvent(auth);
- manager.onEvent(generateNoEvent());
- }, INITIAL_EVENT_TIMEOUT_MS);
- const universalLinksCb = async (eventData) => {
- // We have an event so we can clear the no event timeout
- clearTimeout(noEventTimeout);
- const partialEvent = await _getAndRemoveEvent(auth);
- let finalEvent = null;
- if (partialEvent && (eventData === null || eventData === void 0 ? void 0 : eventData['url'])) {
- finalEvent = _eventFromPartialAndUrl(partialEvent, eventData['url']);
- }
- // If finalEvent is never filled, trigger with no event
- manager.onEvent(finalEvent || generateNoEvent());
- };
- // Universal links subscriber doesn't exist for iOS, so we need to check
- if (typeof universalLinks !== 'undefined' &&
- typeof universalLinks.subscribe === 'function') {
- universalLinks.subscribe(null, universalLinksCb);
- }
- // iOS 7 or 8 custom URL schemes.
- // This is also the current default behavior for iOS 9+.
- // For this to work, cordova-plugin-customurlscheme needs to be installed.
- // https://github.com/EddyVerbruggen/Custom-URL-scheme
- // Do not overwrite the existing developer's URL handler.
- const existingHandleOpenURL = handleOpenURL;
- const packagePrefix = `${BuildInfo.packageName.toLowerCase()}://`;
- _cordovaWindow().handleOpenURL = async (url) => {
- if (url.toLowerCase().startsWith(packagePrefix)) {
- // We want this intentionally to float
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
- universalLinksCb({ url });
- }
- // Call the developer's handler if it is present.
- if (typeof existingHandleOpenURL === 'function') {
- try {
- existingHandleOpenURL(url);
- }
- catch (e) {
- // This is a developer error. Don't stop the flow of the SDK.
- console.error(e);
- }
- }
- };
- }
- }
- /**
- * An implementation of {@link PopupRedirectResolver} suitable for Cordova
- * based applications.
- *
- * @public
- */
- const cordovaPopupRedirectResolver = CordovaPopupRedirectResolver;
- function generateNoEvent() {
- return {
- type: "unknown" /* AuthEventType.UNKNOWN */,
- eventId: null,
- sessionId: null,
- urlResponse: null,
- postBody: null,
- tenantId: null,
- error: _createError("no-auth-event" /* AuthErrorCode.NO_AUTH_EVENT */)
- };
- }
-
- /**
- * @license
- * Copyright 2017 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // This function should only be called by frameworks (e.g. FirebaseUI-web) to log their usage.
- // It is not intended for direct use by developer apps. NO jsdoc here to intentionally leave it out
- // of autogenerated documentation pages to reduce accidental misuse.
- function addFrameworkForLogging(auth, framework) {
- _castAuth(auth)._logFramework(framework);
- }
-
- var name$1 = "@firebase/auth-compat";
- var version$1 = "0.4.2";
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const CORDOVA_ONDEVICEREADY_TIMEOUT_MS = 1000;
- function _getCurrentScheme() {
- var _a;
- return ((_a = self === null || self === void 0 ? void 0 : self.location) === null || _a === void 0 ? void 0 : _a.protocol) || null;
- }
- /**
- * @return {boolean} Whether the current environment is http or https.
- */
- function _isHttpOrHttps() {
- return _getCurrentScheme() === 'http:' || _getCurrentScheme() === 'https:';
- }
- /**
- * @param {?string=} ua The user agent.
- * @return {boolean} Whether the app is rendered in a mobile iOS or Android
- * Cordova environment.
- */
- function _isAndroidOrIosCordovaScheme(ua = getUA()) {
- return !!((_getCurrentScheme() === 'file:' ||
- _getCurrentScheme() === 'ionic:' ||
- _getCurrentScheme() === 'capacitor:') &&
- ua.toLowerCase().match(/iphone|ipad|ipod|android/));
- }
- /**
- * @return {boolean} Whether the environment is a native environment, where
- * CORS checks do not apply.
- */
- function _isNativeEnvironment() {
- return isReactNative() || isNode();
- }
- /**
- * Checks whether the user agent is IE11.
- * @return {boolean} True if it is IE11.
- */
- function _isIe11() {
- return isIE() && (document === null || document === void 0 ? void 0 : document.documentMode) === 11;
- }
- /**
- * Checks whether the user agent is Edge.
- * @param {string} userAgent The browser user agent string.
- * @return {boolean} True if it is Edge.
- */
- function _isEdge(ua = getUA()) {
- return /Edge\/\d+/.test(ua);
- }
- /**
- * @param {?string=} opt_userAgent The navigator user agent.
- * @return {boolean} Whether local storage is not synchronized between an iframe
- * and a popup of the same domain.
- */
- function _isLocalStorageNotSynchronized(ua = getUA()) {
- return _isIe11() || _isEdge(ua);
- }
- /** @return {boolean} Whether web storage is supported. */
- function _isWebStorageSupported() {
- try {
- const storage = self.localStorage;
- const key = _generateEventId();
- if (storage) {
- // setItem will throw an exception if we cannot access WebStorage (e.g.,
- // Safari in private mode).
- storage['setItem'](key, '1');
- storage['removeItem'](key);
- // For browsers where iframe web storage does not synchronize with a popup
- // of the same domain, indexedDB is used for persistent storage. These
- // browsers include IE11 and Edge.
- // Make sure it is supported (IE11 and Edge private mode does not support
- // that).
- if (_isLocalStorageNotSynchronized()) {
- // In such browsers, if indexedDB is not supported, an iframe cannot be
- // notified of the popup sign in result.
- return isIndexedDBAvailable();
- }
- return true;
- }
- }
- catch (e) {
- // localStorage is not available from a worker. Test availability of
- // indexedDB.
- return _isWorker() && isIndexedDBAvailable();
- }
- return false;
- }
- /**
- * @param {?Object=} global The optional global scope.
- * @return {boolean} Whether current environment is a worker.
- */
- function _isWorker() {
- // WorkerGlobalScope only defined in worker environment.
- return (typeof global !== 'undefined' &&
- 'WorkerGlobalScope' in global &&
- 'importScripts' in global);
- }
- function _isPopupRedirectSupported() {
- return ((_isHttpOrHttps() ||
- isBrowserExtension() ||
- _isAndroidOrIosCordovaScheme()) &&
- // React Native with remote debugging reports its location.protocol as
- // http.
- !_isNativeEnvironment() &&
- // Local storage has to be supported for browser popup and redirect
- // operations to work.
- _isWebStorageSupported() &&
- // DOM, popups and redirects are not supported within a worker.
- !_isWorker());
- }
- /** Quick check that indicates the platform *may* be Cordova */
- function _isLikelyCordova() {
- return _isAndroidOrIosCordovaScheme() && typeof document !== 'undefined';
- }
- async function _isCordova() {
- if (!_isLikelyCordova()) {
- return false;
- }
- return new Promise(resolve => {
- const timeoutId = setTimeout(() => {
- // We've waited long enough; the telltale Cordova event didn't happen
- resolve(false);
- }, CORDOVA_ONDEVICEREADY_TIMEOUT_MS);
- document.addEventListener('deviceready', () => {
- clearTimeout(timeoutId);
- resolve(true);
- });
- });
- }
- function _getSelfWindow() {
- return typeof window !== 'undefined' ? window : null;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const Persistence = {
- LOCAL: 'local',
- NONE: 'none',
- SESSION: 'session'
- };
- const _assert$3 = _assert$4;
- const PERSISTENCE_KEY = 'persistence';
- /**
- * Validates that an argument is a valid persistence value. If an invalid type
- * is specified, an error is thrown synchronously.
- */
- function _validatePersistenceArgument(auth, persistence) {
- _assert$3(Object.values(Persistence).includes(persistence), auth, "invalid-persistence-type" /* exp.AuthErrorCode.INVALID_PERSISTENCE */);
- // Validate if the specified type is supported in the current environment.
- if (isReactNative()) {
- // This is only supported in a browser.
- _assert$3(persistence !== Persistence.SESSION, auth, "unsupported-persistence-type" /* exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE */);
- return;
- }
- if (isNode()) {
- // Only none is supported in Node.js.
- _assert$3(persistence === Persistence.NONE, auth, "unsupported-persistence-type" /* exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE */);
- return;
- }
- if (_isWorker()) {
- // In a worker environment, either LOCAL or NONE are supported.
- // If indexedDB not supported and LOCAL provided, throw an error
- _assert$3(persistence === Persistence.NONE ||
- (persistence === Persistence.LOCAL && isIndexedDBAvailable()), auth, "unsupported-persistence-type" /* exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE */);
- return;
- }
- // This is restricted by what the browser supports.
- _assert$3(persistence === Persistence.NONE || _isWebStorageSupported(), auth, "unsupported-persistence-type" /* exp.AuthErrorCode.UNSUPPORTED_PERSISTENCE */);
- }
- async function _savePersistenceForRedirect(auth) {
- await auth._initializationPromise;
- const session = getSessionStorageIfAvailable();
- const key = _persistenceKeyName(PERSISTENCE_KEY, auth.config.apiKey, auth.name);
- if (session) {
- session.setItem(key, auth._getPersistence());
- }
- }
- function _getPersistencesFromRedirect(apiKey, appName) {
- const session = getSessionStorageIfAvailable();
- if (!session) {
- return [];
- }
- const key = _persistenceKeyName(PERSISTENCE_KEY, apiKey, appName);
- const persistence = session.getItem(key);
- switch (persistence) {
- case Persistence.NONE:
- return [inMemoryPersistence];
- case Persistence.LOCAL:
- return [indexedDBLocalPersistence, browserSessionPersistence];
- case Persistence.SESSION:
- return [browserSessionPersistence];
- default:
- return [];
- }
- }
- /** Returns session storage, or null if the property access errors */
- function getSessionStorageIfAvailable() {
- var _a;
- try {
- return ((_a = _getSelfWindow()) === null || _a === void 0 ? void 0 : _a.sessionStorage) || null;
- }
- catch (e) {
- return null;
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const _assert$2 = _assert$4;
- /** Platform-agnostic popup-redirect resolver */
- class CompatPopupRedirectResolver {
- constructor() {
- // Create both resolvers for dynamic resolution later
- this.browserResolver = _getInstance(browserPopupRedirectResolver);
- this.cordovaResolver = _getInstance(cordovaPopupRedirectResolver);
- // The actual resolver in use: either browserResolver or cordovaResolver.
- this.underlyingResolver = null;
- this._redirectPersistence = browserSessionPersistence;
- this._completeRedirectFn = _getRedirectResult;
- this._overrideRedirectResult = _overrideRedirectResult;
- }
- async _initialize(auth) {
- await this.selectUnderlyingResolver();
- return this.assertedUnderlyingResolver._initialize(auth);
- }
- async _openPopup(auth, provider, authType, eventId) {
- await this.selectUnderlyingResolver();
- return this.assertedUnderlyingResolver._openPopup(auth, provider, authType, eventId);
- }
- async _openRedirect(auth, provider, authType, eventId) {
- await this.selectUnderlyingResolver();
- return this.assertedUnderlyingResolver._openRedirect(auth, provider, authType, eventId);
- }
- _isIframeWebStorageSupported(auth, cb) {
- this.assertedUnderlyingResolver._isIframeWebStorageSupported(auth, cb);
- }
- _originValidation(auth) {
- return this.assertedUnderlyingResolver._originValidation(auth);
- }
- get _shouldInitProactively() {
- return _isLikelyCordova() || this.browserResolver._shouldInitProactively;
- }
- get assertedUnderlyingResolver() {
- _assert$2(this.underlyingResolver, "internal-error" /* exp.AuthErrorCode.INTERNAL_ERROR */);
- return this.underlyingResolver;
- }
- async selectUnderlyingResolver() {
- if (this.underlyingResolver) {
- return;
- }
- // We haven't yet determined whether or not we're in Cordova; go ahead
- // and determine that state now.
- const isCordova = await _isCordova();
- this.underlyingResolver = isCordova
- ? this.cordovaResolver
- : this.browserResolver;
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function unwrap(object) {
- return object.unwrap();
- }
- function wrapped(object) {
- return object.wrapped();
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- function credentialFromResponse(userCredential) {
- return credentialFromObject(userCredential);
- }
- function attachExtraErrorFields(auth, e) {
- var _a;
- // The response contains all fields from the server which may or may not
- // actually match the underlying type
- const response = (_a = e.customData) === null || _a === void 0 ? void 0 : _a._tokenResponse;
- if ((e === null || e === void 0 ? void 0 : e.code) === 'auth/multi-factor-auth-required') {
- const mfaErr = e;
- mfaErr.resolver = new MultiFactorResolver(auth, getMultiFactorResolver(auth, e));
- }
- else if (response) {
- const credential = credentialFromObject(e);
- const credErr = e;
- if (credential) {
- credErr.credential = credential;
- credErr.tenantId = response.tenantId || undefined;
- credErr.email = response.email || undefined;
- credErr.phoneNumber = response.phoneNumber || undefined;
- }
- }
- }
- function credentialFromObject(object) {
- const { _tokenResponse } = (object instanceof FirebaseError ? object.customData : object);
- if (!_tokenResponse) {
- return null;
- }
- // Handle phone Auth credential responses, as they have a different format
- // from other backend responses (i.e. no providerId). This is also only the
- // case for user credentials (does not work for errors).
- if (!(object instanceof FirebaseError)) {
- if ('temporaryProof' in _tokenResponse && 'phoneNumber' in _tokenResponse) {
- return PhoneAuthProvider$1.credentialFromResult(object);
- }
- }
- const providerId = _tokenResponse.providerId;
- // Email and password is not supported as there is no situation where the
- // server would return the password to the client.
- if (!providerId || providerId === ProviderId.PASSWORD) {
- return null;
- }
- let provider;
- switch (providerId) {
- case ProviderId.GOOGLE:
- provider = GoogleAuthProvider;
- break;
- case ProviderId.FACEBOOK:
- provider = FacebookAuthProvider;
- break;
- case ProviderId.GITHUB:
- provider = GithubAuthProvider;
- break;
- case ProviderId.TWITTER:
- provider = TwitterAuthProvider;
- break;
- default:
- const { oauthIdToken, oauthAccessToken, oauthTokenSecret, pendingToken, nonce } = _tokenResponse;
- if (!oauthAccessToken &&
- !oauthTokenSecret &&
- !oauthIdToken &&
- !pendingToken) {
- return null;
- }
- // TODO(avolkovi): uncomment this and get it working with SAML & OIDC
- if (pendingToken) {
- if (providerId.startsWith('saml.')) {
- return SAMLAuthCredential._create(providerId, pendingToken);
- }
- else {
- // OIDC and non-default providers excluding Twitter.
- return OAuthCredential._fromParams({
- providerId,
- signInMethod: providerId,
- pendingToken,
- idToken: oauthIdToken,
- accessToken: oauthAccessToken
- });
- }
- }
- return new OAuthProvider(providerId).credential({
- idToken: oauthIdToken,
- accessToken: oauthAccessToken,
- rawNonce: nonce
- });
- }
- return object instanceof FirebaseError
- ? provider.credentialFromError(object)
- : provider.credentialFromResult(object);
- }
- function convertCredential(auth, credentialPromise) {
- return credentialPromise
- .catch(e => {
- if (e instanceof FirebaseError) {
- attachExtraErrorFields(auth, e);
- }
- throw e;
- })
- .then(credential => {
- const operationType = credential.operationType;
- const user = credential.user;
- return {
- operationType,
- credential: credentialFromResponse(credential),
- additionalUserInfo: getAdditionalUserInfo(credential),
- user: User.getOrCreate(user)
- };
- });
- }
- async function convertConfirmationResult(auth, confirmationResultPromise) {
- const confirmationResultExp = await confirmationResultPromise;
- return {
- verificationId: confirmationResultExp.verificationId,
- confirm: (verificationCode) => convertCredential(auth, confirmationResultExp.confirm(verificationCode))
- };
- }
- class MultiFactorResolver {
- constructor(auth, resolver) {
- this.resolver = resolver;
- this.auth = wrapped(auth);
- }
- get session() {
- return this.resolver.session;
- }
- get hints() {
- return this.resolver.hints;
- }
- resolveSignIn(assertion) {
- return convertCredential(unwrap(this.auth), this.resolver.resolveSignIn(assertion));
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class User {
- constructor(_delegate) {
- this._delegate = _delegate;
- this.multiFactor = multiFactor(_delegate);
- }
- static getOrCreate(user) {
- if (!User.USER_MAP.has(user)) {
- User.USER_MAP.set(user, new User(user));
- }
- return User.USER_MAP.get(user);
- }
- delete() {
- return this._delegate.delete();
- }
- reload() {
- return this._delegate.reload();
- }
- toJSON() {
- return this._delegate.toJSON();
- }
- getIdTokenResult(forceRefresh) {
- return this._delegate.getIdTokenResult(forceRefresh);
- }
- getIdToken(forceRefresh) {
- return this._delegate.getIdToken(forceRefresh);
- }
- linkAndRetrieveDataWithCredential(credential) {
- return this.linkWithCredential(credential);
- }
- async linkWithCredential(credential) {
- return convertCredential(this.auth, linkWithCredential(this._delegate, credential));
- }
- async linkWithPhoneNumber(phoneNumber, applicationVerifier) {
- return convertConfirmationResult(this.auth, linkWithPhoneNumber(this._delegate, phoneNumber, applicationVerifier));
- }
- async linkWithPopup(provider) {
- return convertCredential(this.auth, linkWithPopup(this._delegate, provider, CompatPopupRedirectResolver));
- }
- async linkWithRedirect(provider) {
- await _savePersistenceForRedirect(_castAuth(this.auth));
- return linkWithRedirect(this._delegate, provider, CompatPopupRedirectResolver);
- }
- reauthenticateAndRetrieveDataWithCredential(credential) {
- return this.reauthenticateWithCredential(credential);
- }
- async reauthenticateWithCredential(credential) {
- return convertCredential(this.auth, reauthenticateWithCredential(this._delegate, credential));
- }
- reauthenticateWithPhoneNumber(phoneNumber, applicationVerifier) {
- return convertConfirmationResult(this.auth, reauthenticateWithPhoneNumber(this._delegate, phoneNumber, applicationVerifier));
- }
- reauthenticateWithPopup(provider) {
- return convertCredential(this.auth, reauthenticateWithPopup(this._delegate, provider, CompatPopupRedirectResolver));
- }
- async reauthenticateWithRedirect(provider) {
- await _savePersistenceForRedirect(_castAuth(this.auth));
- return reauthenticateWithRedirect(this._delegate, provider, CompatPopupRedirectResolver);
- }
- sendEmailVerification(actionCodeSettings) {
- return sendEmailVerification(this._delegate, actionCodeSettings);
- }
- async unlink(providerId) {
- await unlink(this._delegate, providerId);
- return this;
- }
- updateEmail(newEmail) {
- return updateEmail(this._delegate, newEmail);
- }
- updatePassword(newPassword) {
- return updatePassword(this._delegate, newPassword);
- }
- updatePhoneNumber(phoneCredential) {
- return updatePhoneNumber(this._delegate, phoneCredential);
- }
- updateProfile(profile) {
- return updateProfile(this._delegate, profile);
- }
- verifyBeforeUpdateEmail(newEmail, actionCodeSettings) {
- return verifyBeforeUpdateEmail(this._delegate, newEmail, actionCodeSettings);
- }
- get emailVerified() {
- return this._delegate.emailVerified;
- }
- get isAnonymous() {
- return this._delegate.isAnonymous;
- }
- get metadata() {
- return this._delegate.metadata;
- }
- get phoneNumber() {
- return this._delegate.phoneNumber;
- }
- get providerData() {
- return this._delegate.providerData;
- }
- get refreshToken() {
- return this._delegate.refreshToken;
- }
- get tenantId() {
- return this._delegate.tenantId;
- }
- get displayName() {
- return this._delegate.displayName;
- }
- get email() {
- return this._delegate.email;
- }
- get photoURL() {
- return this._delegate.photoURL;
- }
- get providerId() {
- return this._delegate.providerId;
- }
- get uid() {
- return this._delegate.uid;
- }
- get auth() {
- return this._delegate.auth;
- }
- }
- // Maintain a map so that there's always a 1:1 mapping between new User and
- // legacy compat users
- User.USER_MAP = new WeakMap();
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const _assert$1 = _assert$4;
- class Auth {
- constructor(app, provider) {
- this.app = app;
- if (provider.isInitialized()) {
- this._delegate = provider.getImmediate();
- this.linkUnderlyingAuth();
- return;
- }
- const { apiKey } = app.options;
- // TODO: platform needs to be determined using heuristics
- _assert$1(apiKey, "invalid-api-key" /* exp.AuthErrorCode.INVALID_API_KEY */, {
- appName: app.name
- });
- // TODO: platform needs to be determined using heuristics
- _assert$1(apiKey, "invalid-api-key" /* exp.AuthErrorCode.INVALID_API_KEY */, {
- appName: app.name
- });
- // Only use a popup/redirect resolver in browser environments
- const resolver = typeof window !== 'undefined' ? CompatPopupRedirectResolver : undefined;
- this._delegate = provider.initialize({
- options: {
- persistence: buildPersistenceHierarchy(apiKey, app.name),
- popupRedirectResolver: resolver
- }
- });
- this._delegate._updateErrorMap(debugErrorMap);
- this.linkUnderlyingAuth();
- }
- get emulatorConfig() {
- return this._delegate.emulatorConfig;
- }
- get currentUser() {
- if (!this._delegate.currentUser) {
- return null;
- }
- return User.getOrCreate(this._delegate.currentUser);
- }
- get languageCode() {
- return this._delegate.languageCode;
- }
- set languageCode(languageCode) {
- this._delegate.languageCode = languageCode;
- }
- get settings() {
- return this._delegate.settings;
- }
- get tenantId() {
- return this._delegate.tenantId;
- }
- set tenantId(tid) {
- this._delegate.tenantId = tid;
- }
- useDeviceLanguage() {
- this._delegate.useDeviceLanguage();
- }
- signOut() {
- return this._delegate.signOut();
- }
- useEmulator(url, options) {
- connectAuthEmulator(this._delegate, url, options);
- }
- applyActionCode(code) {
- return applyActionCode(this._delegate, code);
- }
- checkActionCode(code) {
- return checkActionCode(this._delegate, code);
- }
- confirmPasswordReset(code, newPassword) {
- return confirmPasswordReset(this._delegate, code, newPassword);
- }
- async createUserWithEmailAndPassword(email, password) {
- return convertCredential(this._delegate, createUserWithEmailAndPassword(this._delegate, email, password));
- }
- fetchProvidersForEmail(email) {
- return this.fetchSignInMethodsForEmail(email);
- }
- fetchSignInMethodsForEmail(email) {
- return fetchSignInMethodsForEmail(this._delegate, email);
- }
- isSignInWithEmailLink(emailLink) {
- return isSignInWithEmailLink(this._delegate, emailLink);
- }
- async getRedirectResult() {
- _assert$1(_isPopupRedirectSupported(), this._delegate, "operation-not-supported-in-this-environment" /* exp.AuthErrorCode.OPERATION_NOT_SUPPORTED */);
- const credential = await getRedirectResult(this._delegate, CompatPopupRedirectResolver);
- if (!credential) {
- return {
- credential: null,
- user: null
- };
- }
- return convertCredential(this._delegate, Promise.resolve(credential));
- }
- // This function should only be called by frameworks (e.g. FirebaseUI-web) to log their usage.
- // It is not intended for direct use by developer apps. NO jsdoc here to intentionally leave it
- // out of autogenerated documentation pages to reduce accidental misuse.
- addFrameworkForLogging(framework) {
- addFrameworkForLogging(this._delegate, framework);
- }
- onAuthStateChanged(nextOrObserver, errorFn, completed) {
- const { next, error, complete } = wrapObservers(nextOrObserver, errorFn, completed);
- return this._delegate.onAuthStateChanged(next, error, complete);
- }
- onIdTokenChanged(nextOrObserver, errorFn, completed) {
- const { next, error, complete } = wrapObservers(nextOrObserver, errorFn, completed);
- return this._delegate.onIdTokenChanged(next, error, complete);
- }
- sendSignInLinkToEmail(email, actionCodeSettings) {
- return sendSignInLinkToEmail(this._delegate, email, actionCodeSettings);
- }
- sendPasswordResetEmail(email, actionCodeSettings) {
- return sendPasswordResetEmail(this._delegate, email, actionCodeSettings || undefined);
- }
- async setPersistence(persistence) {
- _validatePersistenceArgument(this._delegate, persistence);
- let converted;
- switch (persistence) {
- case Persistence.SESSION:
- converted = browserSessionPersistence;
- break;
- case Persistence.LOCAL:
- // Not using isIndexedDBAvailable() since it only checks if indexedDB is defined.
- const isIndexedDBFullySupported = await _getInstance(indexedDBLocalPersistence)
- ._isAvailable();
- converted = isIndexedDBFullySupported
- ? indexedDBLocalPersistence
- : browserLocalPersistence;
- break;
- case Persistence.NONE:
- converted = inMemoryPersistence;
- break;
- default:
- return _fail("argument-error" /* exp.AuthErrorCode.ARGUMENT_ERROR */, {
- appName: this._delegate.name
- });
- }
- return this._delegate.setPersistence(converted);
- }
- signInAndRetrieveDataWithCredential(credential) {
- return this.signInWithCredential(credential);
- }
- signInAnonymously() {
- return convertCredential(this._delegate, signInAnonymously(this._delegate));
- }
- signInWithCredential(credential) {
- return convertCredential(this._delegate, signInWithCredential(this._delegate, credential));
- }
- signInWithCustomToken(token) {
- return convertCredential(this._delegate, signInWithCustomToken(this._delegate, token));
- }
- signInWithEmailAndPassword(email, password) {
- return convertCredential(this._delegate, signInWithEmailAndPassword(this._delegate, email, password));
- }
- signInWithEmailLink(email, emailLink) {
- return convertCredential(this._delegate, signInWithEmailLink(this._delegate, email, emailLink));
- }
- signInWithPhoneNumber(phoneNumber, applicationVerifier) {
- return convertConfirmationResult(this._delegate, signInWithPhoneNumber(this._delegate, phoneNumber, applicationVerifier));
- }
- async signInWithPopup(provider) {
- _assert$1(_isPopupRedirectSupported(), this._delegate, "operation-not-supported-in-this-environment" /* exp.AuthErrorCode.OPERATION_NOT_SUPPORTED */);
- return convertCredential(this._delegate, signInWithPopup(this._delegate, provider, CompatPopupRedirectResolver));
- }
- async signInWithRedirect(provider) {
- _assert$1(_isPopupRedirectSupported(), this._delegate, "operation-not-supported-in-this-environment" /* exp.AuthErrorCode.OPERATION_NOT_SUPPORTED */);
- await _savePersistenceForRedirect(this._delegate);
- return signInWithRedirect(this._delegate, provider, CompatPopupRedirectResolver);
- }
- updateCurrentUser(user) {
- // remove ts-ignore once overloads are defined for exp functions to accept compat objects
- // @ts-ignore
- return this._delegate.updateCurrentUser(user);
- }
- verifyPasswordResetCode(code) {
- return verifyPasswordResetCode(this._delegate, code);
- }
- unwrap() {
- return this._delegate;
- }
- _delete() {
- return this._delegate._delete();
- }
- linkUnderlyingAuth() {
- this._delegate.wrapped = () => this;
- }
- }
- Auth.Persistence = Persistence;
- function wrapObservers(nextOrObserver, error, complete) {
- let next = nextOrObserver;
- if (typeof nextOrObserver !== 'function') {
- ({ next, error, complete } = nextOrObserver);
- }
- // We know 'next' is now a function
- const oldNext = next;
- const newNext = (user) => oldNext(user && User.getOrCreate(user));
- return {
- next: newNext,
- error: error,
- complete
- };
- }
- function buildPersistenceHierarchy(apiKey, appName) {
- // Note this is slightly different behavior: in this case, the stored
- // persistence is checked *first* rather than last. This is because we want
- // to prefer stored persistence type in the hierarchy. This is an empty
- // array if window is not available or there is no pending redirect
- const persistences = _getPersistencesFromRedirect(apiKey, appName);
- // If "self" is available, add indexedDB
- if (typeof self !== 'undefined' &&
- !persistences.includes(indexedDBLocalPersistence)) {
- persistences.push(indexedDBLocalPersistence);
- }
- // If "window" is available, add HTML Storage persistences
- if (typeof window !== 'undefined') {
- for (const persistence of [
- browserLocalPersistence,
- browserSessionPersistence
- ]) {
- if (!persistences.includes(persistence)) {
- persistences.push(persistence);
- }
- }
- }
- // Add in-memory as a final fallback
- if (!persistences.includes(inMemoryPersistence)) {
- persistences.push(inMemoryPersistence);
- }
- return persistences;
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- class PhoneAuthProvider {
- constructor() {
- this.providerId = 'phone';
- // TODO: remove ts-ignore when moving types from auth-types to auth-compat
- // @ts-ignore
- this._delegate = new PhoneAuthProvider$1(unwrap(firebase.auth()));
- }
- static credential(verificationId, verificationCode) {
- return PhoneAuthProvider$1.credential(verificationId, verificationCode);
- }
- verifyPhoneNumber(phoneInfoOptions, applicationVerifier) {
- return this._delegate.verifyPhoneNumber(
- // The implementation matches but the types are subtly incompatible
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- phoneInfoOptions, applicationVerifier);
- }
- unwrap() {
- return this._delegate;
- }
- }
- PhoneAuthProvider.PHONE_SIGN_IN_METHOD = PhoneAuthProvider$1.PHONE_SIGN_IN_METHOD;
- PhoneAuthProvider.PROVIDER_ID = PhoneAuthProvider$1.PROVIDER_ID;
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const _assert = _assert$4;
- class RecaptchaVerifier {
- constructor(container, parameters, app = firebase.app()) {
- var _a;
- // API key is required for web client RPC calls.
- _assert((_a = app.options) === null || _a === void 0 ? void 0 : _a.apiKey, "invalid-api-key" /* exp.AuthErrorCode.INVALID_API_KEY */, {
- appName: app.name
- });
- this._delegate = new RecaptchaVerifier$1(container,
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- parameters,
- // TODO: remove ts-ignore when moving types from auth-types to auth-compat
- // @ts-ignore
- app.auth());
- this.type = this._delegate.type;
- }
- clear() {
- this._delegate.clear();
- }
- render() {
- return this._delegate.render();
- }
- verify() {
- return this._delegate.verify();
- }
- }
-
- /**
- * @license
- * Copyright 2020 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const AUTH_TYPE = 'auth-compat';
- // Create auth components to register with firebase.
- // Provides Auth public APIs.
- function registerAuthCompat(instance) {
- instance.INTERNAL.registerComponent(new Component(AUTH_TYPE, container => {
- // getImmediate for FirebaseApp will always succeed
- const app = container.getProvider('app-compat').getImmediate();
- const authProvider = container.getProvider('auth');
- return new Auth(app, authProvider);
- }, "PUBLIC" /* ComponentType.PUBLIC */)
- .setServiceProps({
- ActionCodeInfo: {
- Operation: {
- EMAIL_SIGNIN: ActionCodeOperation.EMAIL_SIGNIN,
- PASSWORD_RESET: ActionCodeOperation.PASSWORD_RESET,
- RECOVER_EMAIL: ActionCodeOperation.RECOVER_EMAIL,
- REVERT_SECOND_FACTOR_ADDITION: ActionCodeOperation.REVERT_SECOND_FACTOR_ADDITION,
- VERIFY_AND_CHANGE_EMAIL: ActionCodeOperation.VERIFY_AND_CHANGE_EMAIL,
- VERIFY_EMAIL: ActionCodeOperation.VERIFY_EMAIL
- }
- },
- EmailAuthProvider: EmailAuthProvider,
- FacebookAuthProvider: FacebookAuthProvider,
- GithubAuthProvider: GithubAuthProvider,
- GoogleAuthProvider: GoogleAuthProvider,
- OAuthProvider: OAuthProvider,
- SAMLAuthProvider: SAMLAuthProvider,
- PhoneAuthProvider: PhoneAuthProvider,
- PhoneMultiFactorGenerator: PhoneMultiFactorGenerator,
- RecaptchaVerifier: RecaptchaVerifier,
- TwitterAuthProvider: TwitterAuthProvider,
- Auth,
- AuthCredential: AuthCredential,
- Error: FirebaseError
- })
- .setInstantiationMode("LAZY" /* InstantiationMode.LAZY */)
- .setMultipleInstances(false));
- instance.registerVersion(name$1, version$1);
- }
- registerAuthCompat(firebase);
-
- /* src/components/misccomponents/LoadingCircle.svelte generated by Svelte v3.59.1 */
-
- const file$T = "src/components/misccomponents/LoadingCircle.svelte";
-
- function create_fragment$T(ctx) {
- let div;
-
- const block = {
- c: function create() {
- div = element("div");
- attr_dev(div, "class", "spinner inline-block align-middle mx-1 svelte-69u30n");
- add_location(div, file$T, 34, 0, 546);
- },
- l: function claim(nodes) {
- throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
- },
- m: function mount(target, anchor) {
- insert_dev(target, div, anchor);
- },
- p: noop$1,
- i: noop$1,
- o: noop$1,
- d: function destroy(detaching) {
- if (detaching) detach_dev(div);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_fragment$T.name,
- type: "component",
- source: "",
- ctx
- });
-
- return block;
- }
-
- function instance$T($$self, $$props) {
- let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots('LoadingCircle', slots, []);
- const writable_props = [];
-
- Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
- });
-
- return [];
- }
-
- class LoadingCircle extends SvelteComponentDev {
- constructor(options) {
- super(options);
- init(this, options, instance$T, create_fragment$T, safe_not_equal, {});
-
- dispatch_dev("SvelteRegisterComponent", {
- component: this,
- tagName: "LoadingCircle",
- options,
- id: create_fragment$T.name
- });
- }
- }
-
- /* src/components/misccomponents/TextField.svelte generated by Svelte v3.59.1 */
- const file$S = "src/components/misccomponents/TextField.svelte";
-
- // (126:0) {#if required && !value}
- function create_if_block_1$t(ctx) {
- let p;
-
- const block = {
- c: function create() {
- p = element("p");
- p.textContent = "This field is required";
- attr_dev(p, "class", "text-red-500 text-xs italic");
- add_location(p, file$S, 126, 2, 3203);
- },
- m: function mount(target, anchor) {
- insert_dev(target, p, anchor);
- },
- d: function destroy(detaching) {
- if (detaching) detach_dev(p);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_if_block_1$t.name,
- type: "if",
- source: "(126:0) {#if required && !value}",
- ctx
- });
-
- return block;
- }
-
- // (130:0) {#if errorMsg && value}
- function create_if_block$G(ctx) {
- let p;
- let t;
-
- const block = {
- c: function create() {
- p = element("p");
- t = text(/*errorMsg*/ ctx[2]);
- attr_dev(p, "class", "text-red-500 text-xs italic");
- add_location(p, file$S, 130, 2, 3302);
- },
- m: function mount(target, anchor) {
- insert_dev(target, p, anchor);
- append_dev(p, t);
- },
- p: function update(ctx, dirty) {
- if (dirty & /*errorMsg*/ 4) set_data_dev(t, /*errorMsg*/ ctx[2]);
- },
- d: function destroy(detaching) {
- if (detaching) detach_dev(p);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_if_block$G.name,
- type: "if",
- source: "(130:0) {#if errorMsg && value}",
- ctx
- });
-
- return block;
- }
-
- function create_fragment$S(ctx) {
- let label_1;
- let t0;
- let t1;
- let input;
- let t2;
- let t3;
- let if_block1_anchor;
- let mounted;
- let dispose;
- let if_block0 = /*required*/ ctx[5] && !/*value*/ ctx[0] && create_if_block_1$t(ctx);
- let if_block1 = /*errorMsg*/ ctx[2] && /*value*/ ctx[0] && create_if_block$G(ctx);
-
- const block = {
- c: function create() {
- label_1 = element("label");
- t0 = text(/*label*/ ctx[1]);
- t1 = space();
- input = element("input");
- t2 = space();
- if (if_block0) if_block0.c();
- t3 = space();
- if (if_block1) if_block1.c();
- if_block1_anchor = empty();
- attr_dev(label_1, "class", "block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2");
- add_location(label_1, file$S, 108, 0, 2670);
- attr_dev(input, "class", "appearance-none block w-full text-gray-700 border border-gray-300 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500 svelte-12emz5j");
- attr_dev(input, "placeholder", /*placeholder*/ ctx[6]);
- attr_dev(input, "autocomplete", /*autocomplete*/ ctx[4]);
- input.value = /*value*/ ctx[0];
- attr_dev(input, "type", /*type*/ ctx[3]);
- toggle_class(input, "border-red-300", /*required*/ ctx[5] && !/*value*/ ctx[0] || /*errorMsg*/ ctx[2]);
- toggle_class(input, "focus:border-red-500", /*required*/ ctx[5] && !/*value*/ ctx[0] || /*errorMsg*/ ctx[2]);
- add_location(input, file$S, 112, 0, 2774);
- },
- l: function claim(nodes) {
- throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
- },
- m: function mount(target, anchor) {
- insert_dev(target, label_1, anchor);
- append_dev(label_1, t0);
- insert_dev(target, t1, anchor);
- insert_dev(target, input, anchor);
- insert_dev(target, t2, anchor);
- if (if_block0) if_block0.m(target, anchor);
- insert_dev(target, t3, anchor);
- if (if_block1) if_block1.m(target, anchor);
- insert_dev(target, if_block1_anchor, anchor);
-
- if (!mounted) {
- dispose = [
- listen_dev(input, "input", /*handleInput*/ ctx[8], false, false, false, false),
- listen_dev(input, "keydown", /*enterKey*/ ctx[7], false, false, false, false)
- ];
-
- mounted = true;
- }
- },
- p: function update(ctx, [dirty]) {
- if (dirty & /*label*/ 2) set_data_dev(t0, /*label*/ ctx[1]);
-
- if (dirty & /*placeholder*/ 64) {
- attr_dev(input, "placeholder", /*placeholder*/ ctx[6]);
- }
-
- if (dirty & /*autocomplete*/ 16) {
- attr_dev(input, "autocomplete", /*autocomplete*/ ctx[4]);
- }
-
- if (dirty & /*value*/ 1 && input.value !== /*value*/ ctx[0]) {
- prop_dev(input, "value", /*value*/ ctx[0]);
- }
-
- if (dirty & /*type*/ 8) {
- attr_dev(input, "type", /*type*/ ctx[3]);
- }
-
- if (dirty & /*required, value, errorMsg*/ 37) {
- toggle_class(input, "border-red-300", /*required*/ ctx[5] && !/*value*/ ctx[0] || /*errorMsg*/ ctx[2]);
- }
-
- if (dirty & /*required, value, errorMsg*/ 37) {
- toggle_class(input, "focus:border-red-500", /*required*/ ctx[5] && !/*value*/ ctx[0] || /*errorMsg*/ ctx[2]);
- }
-
- if (/*required*/ ctx[5] && !/*value*/ ctx[0]) {
- if (if_block0) ; else {
- if_block0 = create_if_block_1$t(ctx);
- if_block0.c();
- if_block0.m(t3.parentNode, t3);
- }
- } else if (if_block0) {
- if_block0.d(1);
- if_block0 = null;
- }
-
- if (/*errorMsg*/ ctx[2] && /*value*/ ctx[0]) {
- if (if_block1) {
- if_block1.p(ctx, dirty);
- } else {
- if_block1 = create_if_block$G(ctx);
- if_block1.c();
- if_block1.m(if_block1_anchor.parentNode, if_block1_anchor);
- }
- } else if (if_block1) {
- if_block1.d(1);
- if_block1 = null;
- }
- },
- i: noop$1,
- o: noop$1,
- d: function destroy(detaching) {
- if (detaching) detach_dev(label_1);
- if (detaching) detach_dev(t1);
- if (detaching) detach_dev(input);
- if (detaching) detach_dev(t2);
- if (if_block0) if_block0.d(detaching);
- if (detaching) detach_dev(t3);
- if (if_block1) if_block1.d(detaching);
- if (detaching) detach_dev(if_block1_anchor);
- mounted = false;
- run_all(dispose);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_fragment$S.name,
- type: "component",
- source: "",
- ctx
- });
-
- return block;
- }
-
- function instance$S($$self, $$props, $$invalidate) {
- let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots('TextField', slots, []);
- const dispatch = createEventDispatcher();
- let { label } = $$props;
- let { value = "" } = $$props;
- let { errorMsg = "" } = $$props;
- let { type = "text" } = $$props;
- let { autocomplete = "" } = $$props;
- let { required = true } = $$props;
- let { placeholder = "" } = $$props;
- const enterKey = key => key.code === "Enter" && dispatch("enterKey");
-
- const handleInput = e => {
- // in here, you can switch on type and implement
- // whatever behaviour you need
- $$invalidate(0, value = type.match(/^(number|range)$/)
- ? +e.target.value
- : e.target.value);
- };
-
- $$self.$$.on_mount.push(function () {
- if (label === undefined && !('label' in $$props || $$self.$$.bound[$$self.$$.props['label']])) {
- console.warn(" was created without expected prop 'label'");
- }
- });
-
- const writable_props = [
- 'label',
- 'value',
- 'errorMsg',
- 'type',
- 'autocomplete',
- 'required',
- 'placeholder'
- ];
-
- Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
- });
-
- $$self.$$set = $$props => {
- if ('label' in $$props) $$invalidate(1, label = $$props.label);
- if ('value' in $$props) $$invalidate(0, value = $$props.value);
- if ('errorMsg' in $$props) $$invalidate(2, errorMsg = $$props.errorMsg);
- if ('type' in $$props) $$invalidate(3, type = $$props.type);
- if ('autocomplete' in $$props) $$invalidate(4, autocomplete = $$props.autocomplete);
- if ('required' in $$props) $$invalidate(5, required = $$props.required);
- if ('placeholder' in $$props) $$invalidate(6, placeholder = $$props.placeholder);
- };
-
- $$self.$capture_state = () => ({
- createEventDispatcher,
- dispatch,
- label,
- value,
- errorMsg,
- type,
- autocomplete,
- required,
- placeholder,
- enterKey,
- handleInput
- });
-
- $$self.$inject_state = $$props => {
- if ('label' in $$props) $$invalidate(1, label = $$props.label);
- if ('value' in $$props) $$invalidate(0, value = $$props.value);
- if ('errorMsg' in $$props) $$invalidate(2, errorMsg = $$props.errorMsg);
- if ('type' in $$props) $$invalidate(3, type = $$props.type);
- if ('autocomplete' in $$props) $$invalidate(4, autocomplete = $$props.autocomplete);
- if ('required' in $$props) $$invalidate(5, required = $$props.required);
- if ('placeholder' in $$props) $$invalidate(6, placeholder = $$props.placeholder);
- };
-
- if ($$props && "$$inject" in $$props) {
- $$self.$inject_state($$props.$$inject);
- }
-
- return [
- value,
- label,
- errorMsg,
- type,
- autocomplete,
- required,
- placeholder,
- enterKey,
- handleInput
- ];
- }
-
- class TextField extends SvelteComponentDev {
- constructor(options) {
- super(options);
-
- init(this, options, instance$S, create_fragment$S, safe_not_equal, {
- label: 1,
- value: 0,
- errorMsg: 2,
- type: 3,
- autocomplete: 4,
- required: 5,
- placeholder: 6
- });
-
- dispatch_dev("SvelteRegisterComponent", {
- component: this,
- tagName: "TextField",
- options,
- id: create_fragment$S.name
- });
- }
-
- get label() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set label(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
-
- get value() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set value(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
-
- get errorMsg() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set errorMsg(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
-
- get type() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set type(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
-
- get autocomplete() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set autocomplete(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
-
- get required() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set required(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
-
- get placeholder() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set placeholder(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
- }
-
- /* src/components/misccomponents/SocialLogin.svelte generated by Svelte v3.59.1 */
- const file$R = "src/components/misccomponents/SocialLogin.svelte";
-
- // (75:4) {#if loading}
- function create_if_block_1$s(ctx) {
- let loadingcirle;
- let current;
- loadingcirle = new LoadingCircle({ $$inline: true });
-
- const block = {
- c: function create() {
- create_component(loadingcirle.$$.fragment);
- },
- m: function mount(target, anchor) {
- mount_component(loadingcirle, target, anchor);
- current = true;
- },
- i: function intro(local) {
- if (current) return;
- transition_in(loadingcirle.$$.fragment, local);
- current = true;
- },
- o: function outro(local) {
- transition_out(loadingcirle.$$.fragment, local);
- current = false;
- },
- d: function destroy(detaching) {
- destroy_component(loadingcirle, detaching);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_if_block_1$s.name,
- type: "if",
- source: "(75:4) {#if loading}",
- ctx
- });
-
- return block;
- }
-
- // (102:4) {#if loading}
- function create_if_block$F(ctx) {
- let loadingcirle;
- let current;
- loadingcirle = new LoadingCircle({ $$inline: true });
-
- const block = {
- c: function create() {
- create_component(loadingcirle.$$.fragment);
- },
- m: function mount(target, anchor) {
- mount_component(loadingcirle, target, anchor);
- current = true;
- },
- i: function intro(local) {
- if (current) return;
- transition_in(loadingcirle.$$.fragment, local);
- current = true;
- },
- o: function outro(local) {
- transition_out(loadingcirle.$$.fragment, local);
- current = false;
- },
- d: function destroy(detaching) {
- destroy_component(loadingcirle, detaching);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_if_block$F.name,
- type: "if",
- source: "(102:4) {#if loading}",
- ctx
- });
-
- return block;
- }
-
- function create_fragment$R(ctx) {
- let div0;
- let button0;
- let svg0;
- let path0;
- let path1;
- let path2;
- let path3;
- let t0;
- let t1;
- let div1;
- let button1;
- let svg1;
- let path4;
- let t2;
- let current;
- let mounted;
- let dispose;
- let if_block0 = /*loading*/ ctx[0] && create_if_block_1$s(ctx);
- let if_block1 = /*loading*/ ctx[0] && create_if_block$F(ctx);
-
- const block = {
- c: function create() {
- div0 = element("div");
- button0 = element("button");
- svg0 = svg_element("svg");
- path0 = svg_element("path");
- path1 = svg_element("path");
- path2 = svg_element("path");
- path3 = svg_element("path");
- t0 = text("\n Sign In Using Google\n ");
- if (if_block0) if_block0.c();
- t1 = space();
- div1 = element("div");
- button1 = element("button");
- svg1 = svg_element("svg");
- path4 = svg_element("path");
- t2 = text("\n Sign In Using Facebook\n ");
- if (if_block1) if_block1.c();
- attr_dev(path0, "d", "M255.878\n 133.451c0-10.734-.871-18.567-2.756-26.69H130.55v48.448h71.947c-1.45\n 12.04-9.283 30.172-26.69 42.356l-.244 1.622 38.755 30.023\n 2.685.268c24.659-22.774 38.875-56.282 38.875-96.027");
- attr_dev(path0, "fill", "#4285F4");
- add_location(path0, file$R, 49, 6, 1149);
- attr_dev(path1, "d", "M130.55 261.1c35.248 0 64.839-11.605\n 86.453-31.622l-41.196-31.913c-11.024 7.688-25.82 13.055-45.257\n 13.055-34.523 0-63.824-22.773-74.269-54.25l-1.531.13-40.298 31.187-.527\n 1.465C35.393 231.798 79.49 261.1 130.55 261.1");
- attr_dev(path1, "fill", "#34A853");
- add_location(path1, file$R, 55, 6, 1410);
- attr_dev(path2, "d", "M56.281 156.37c-2.756-8.123-4.351-16.827-4.351-25.82 0-8.994\n 1.595-17.697 4.206-25.82l-.073-1.73L15.26 71.312l-1.335.635C5.077 89.644\n 0 109.517 0 130.55s5.077 40.905 13.925 58.602l42.356-32.782");
- attr_dev(path2, "fill", "#FBBC05");
- add_location(path2, file$R, 61, 6, 1702);
- attr_dev(path3, "d", "M130.55 50.479c24.514 0 41.05 10.589 50.479\n 19.438l36.844-35.974C195.245 12.91 165.798 0 130.55 0 79.49 0 35.393\n 29.301 13.925 71.947l42.211 32.783c10.59-31.477 39.891-54.251\n 74.414-54.251");
- attr_dev(path3, "fill", "#EB4335");
- add_location(path3, file$R, 66, 6, 1962);
- attr_dev(svg0, "width", "22");
- attr_dev(svg0, "height", "22");
- attr_dev(svg0, "class", "inline-block mr-1");
- attr_dev(svg0, "viewBox", "0 0 256 262");
- attr_dev(svg0, "xmlns", "http://www.w3.org/2000/svg");
- attr_dev(svg0, "preserveAspectRatio", "xMidYMid");
- add_location(svg0, file$R, 42, 4, 964);
- attr_dev(button0, "type", "button");
- button0.disabled = /*loading*/ ctx[0];
- attr_dev(button0, "class", "social bg-white hover:bg-red-400 block hover:text-white py-2 px-4 border border-red-700 hover:border-transparent rounded svelte-fjaw1s");
- add_location(button0, file$R, 36, 2, 732);
- attr_dev(div0, "class", "mb-2 mx-auto");
- add_location(div0, file$R, 35, 0, 703);
- attr_dev(path4, "d", "M158.232 219.912v-94.461h31.707l4.747-36.813h-36.454V65.134c0-10.658\n 2.96-17.922\n 18.245-17.922l19.494-.009V14.278c-3.373-.447-14.944-1.449-28.406-1.449-28.106\n 0-47.348 17.155-47.348\n 48.661v27.149H88.428v36.813h31.788v94.461l38.016-.001z");
- attr_dev(path4, "fill", "#3c5a9a");
- add_location(path4, file$R, 92, 6, 2752);
- attr_dev(svg1, "xmlns", "http://www.w3.org/2000/svg");
- attr_dev(svg1, "width", "22");
- attr_dev(svg1, "height", "22");
- attr_dev(svg1, "class", "inline-block");
- attr_dev(svg1, "viewBox", "88.428 12.828 107.543 207.085");
- add_location(svg1, file$R, 86, 4, 2591);
- attr_dev(button1, "type", "button");
- button1.disabled = /*loading*/ ctx[0];
- attr_dev(button1, "class", "social bg-white hover:bg-blue-500 block hover:text-white py-2 px-4 border border-blue-700 hover:border-transparent rounded svelte-fjaw1s");
- add_location(button1, file$R, 80, 2, 2354);
- attr_dev(div1, "class", "mb-4 mx-auto");
- add_location(div1, file$R, 79, 0, 2325);
- },
- l: function claim(nodes) {
- throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
- },
- m: function mount(target, anchor) {
- insert_dev(target, div0, anchor);
- append_dev(div0, button0);
- append_dev(button0, svg0);
- append_dev(svg0, path0);
- append_dev(svg0, path1);
- append_dev(svg0, path2);
- append_dev(svg0, path3);
- append_dev(button0, t0);
- if (if_block0) if_block0.m(button0, null);
- insert_dev(target, t1, anchor);
- insert_dev(target, div1, anchor);
- append_dev(div1, button1);
- append_dev(button1, svg1);
- append_dev(svg1, path4);
- append_dev(button1, t2);
- if (if_block1) if_block1.m(button1, null);
- current = true;
-
- if (!mounted) {
- dispose = [
- listen_dev(button0, "click", prevent_default(/*loginGmail*/ ctx[1]), false, true, false, false),
- listen_dev(button1, "click", prevent_default(/*loginFacebook*/ ctx[2]), false, true, false, false)
- ];
-
- mounted = true;
- }
- },
- p: function update(ctx, [dirty]) {
- if (/*loading*/ ctx[0]) {
- if (if_block0) {
- if (dirty & /*loading*/ 1) {
- transition_in(if_block0, 1);
- }
- } else {
- if_block0 = create_if_block_1$s(ctx);
- if_block0.c();
- transition_in(if_block0, 1);
- if_block0.m(button0, null);
- }
- } else if (if_block0) {
- group_outros();
-
- transition_out(if_block0, 1, 1, () => {
- if_block0 = null;
- });
-
- check_outros();
- }
-
- if (!current || dirty & /*loading*/ 1) {
- prop_dev(button0, "disabled", /*loading*/ ctx[0]);
- }
-
- if (/*loading*/ ctx[0]) {
- if (if_block1) {
- if (dirty & /*loading*/ 1) {
- transition_in(if_block1, 1);
- }
- } else {
- if_block1 = create_if_block$F(ctx);
- if_block1.c();
- transition_in(if_block1, 1);
- if_block1.m(button1, null);
- }
- } else if (if_block1) {
- group_outros();
-
- transition_out(if_block1, 1, 1, () => {
- if_block1 = null;
- });
-
- check_outros();
- }
-
- if (!current || dirty & /*loading*/ 1) {
- prop_dev(button1, "disabled", /*loading*/ ctx[0]);
- }
- },
- i: function intro(local) {
- if (current) return;
- transition_in(if_block0);
- transition_in(if_block1);
- current = true;
- },
- o: function outro(local) {
- transition_out(if_block0);
- transition_out(if_block1);
- current = false;
- },
- d: function destroy(detaching) {
- if (detaching) detach_dev(div0);
- if (if_block0) if_block0.d();
- if (detaching) detach_dev(t1);
- if (detaching) detach_dev(div1);
- if (if_block1) if_block1.d();
- mounted = false;
- run_all(dispose);
- }
- };
-
- dispatch_dev("SvelteRegisterBlock", {
- block,
- id: create_fragment$R.name,
- type: "component",
- source: "",
- ctx
- });
-
- return block;
- }
-
- function instance$R($$self, $$props, $$invalidate) {
- let { $$slots: slots = {}, $$scope } = $$props;
- validate_slots('SocialLogin', slots, []);
- let loading;
-
- const login = promise => {
- $$invalidate(3, serverError = "");
- $$invalidate(0, loading = true);
- return promise.catch(err => $$invalidate(3, serverError = err.message)).finally(() => $$invalidate(0, loading = false));
- };
-
- const loginGmail = () => login(firebase.auth().signInWithRedirect(new firebase.auth.GoogleAuthProvider()));
- const loginFacebook = () => login(firebase.auth().signInWithRedirect(new firebase.auth.FacebookAuthProvider()));
- let { serverError } = $$props;
-
- $$self.$$.on_mount.push(function () {
- if (serverError === undefined && !('serverError' in $$props || $$self.$$.bound[$$self.$$.props['serverError']])) {
- console.warn(" was created without expected prop 'serverError'");
- }
- });
-
- const writable_props = ['serverError'];
-
- Object.keys($$props).forEach(key => {
- if (!~writable_props.indexOf(key) && key.slice(0, 2) !== '$$' && key !== 'slot') console.warn(` was created with unknown prop '${key}'`);
- });
-
- $$self.$$set = $$props => {
- if ('serverError' in $$props) $$invalidate(3, serverError = $$props.serverError);
- };
-
- $$self.$capture_state = () => ({
- firebase,
- LoadingCirle: LoadingCircle,
- loading,
- login,
- loginGmail,
- loginFacebook,
- serverError
- });
-
- $$self.$inject_state = $$props => {
- if ('loading' in $$props) $$invalidate(0, loading = $$props.loading);
- if ('serverError' in $$props) $$invalidate(3, serverError = $$props.serverError);
- };
-
- if ($$props && "$$inject" in $$props) {
- $$self.$inject_state($$props.$$inject);
- }
-
- return [loading, loginGmail, loginFacebook, serverError];
- }
-
- class SocialLogin extends SvelteComponentDev {
- constructor(options) {
- super(options);
- init(this, options, instance$R, create_fragment$R, safe_not_equal, { serverError: 3 });
-
- dispatch_dev("SvelteRegisterComponent", {
- component: this,
- tagName: "SocialLogin",
- options,
- id: create_fragment$R.name
- });
- }
-
- get serverError() {
- throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''");
- }
-
- set serverError(value) {
- throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''");
- }
- }
-
- var So$1={166:{"value":"00A6","name":"BROKEN BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BROKEN VERTICAL BAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\xA6"},169:{"value":"00A9","name":"COPYRIGHT SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\xA9"},174:{"value":"00AE","name":"REGISTERED SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"REGISTERED TRADE MARK SIGN","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\xAE"},176:{"value":"00B0","name":"DEGREE SIGN","category":"So","class":"0","bidirectional_category":"ET","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\xB0"},1154:{"value":"0482","name":"CYRILLIC THOUSANDS SIGN","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0482"},1421:{"value":"058D","name":"RIGHT-FACING ARMENIAN ETERNITY SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u058D"},1422:{"value":"058E","name":"LEFT-FACING ARMENIAN ETERNITY SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u058E"},1550:{"value":"060E","name":"ARABIC POETIC VERSE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u060E"},1551:{"value":"060F","name":"ARABIC SIGN MISRA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u060F"},1758:{"value":"06DE","name":"ARABIC START OF RUB EL HIZB","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u06DE"},1769:{"value":"06E9","name":"ARABIC PLACE OF SAJDAH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u06E9"},1789:{"value":"06FD","name":"ARABIC SIGN SINDHI AMPERSAND","category":"So","class":"0","bidirectional_category":"AL","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u06FD"},1790:{"value":"06FE","name":"ARABIC SIGN SINDHI POSTPOSITION MEN","category":"So","class":"0","bidirectional_category":"AL","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u06FE"},2038:{"value":"07F6","name":"NKO SYMBOL OO DENNEN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u07F6"},2554:{"value":"09FA","name":"BENGALI ISSHAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u09FA"},2928:{"value":"0B70","name":"ORIYA ISSHAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0B70"},3059:{"value":"0BF3","name":"TAMIL DAY SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0BF3"},3060:{"value":"0BF4","name":"TAMIL MONTH SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0BF4"},3061:{"value":"0BF5","name":"TAMIL YEAR SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0BF5"},3062:{"value":"0BF6","name":"TAMIL DEBIT SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0BF6"},3063:{"value":"0BF7","name":"TAMIL CREDIT SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0BF7"},3064:{"value":"0BF8","name":"TAMIL AS ABOVE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0BF8"},3066:{"value":"0BFA","name":"TAMIL NUMBER SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0BFA"},3199:{"value":"0C7F","name":"TELUGU SIGN TUUMU","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0C7F"},3407:{"value":"0D4F","name":"MALAYALAM SIGN PARA","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0D4F"},3449:{"value":"0D79","name":"MALAYALAM DATE MARK","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0D79"},3841:{"value":"0F01","name":"TIBETAN MARK GTER YIG MGO TRUNCATED A","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F01"},3842:{"value":"0F02","name":"TIBETAN MARK GTER YIG MGO -UM RNAM BCAD MA","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F02"},3843:{"value":"0F03","name":"TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F03"},3859:{"value":"0F13","name":"TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F13"},3861:{"value":"0F15","name":"TIBETAN LOGOTYPE SIGN CHAD RTAGS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F15"},3862:{"value":"0F16","name":"TIBETAN LOGOTYPE SIGN LHAG RTAGS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F16"},3863:{"value":"0F17","name":"TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F17"},3866:{"value":"0F1A","name":"TIBETAN SIGN RDEL DKAR GCIG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F1A"},3867:{"value":"0F1B","name":"TIBETAN SIGN RDEL DKAR GNYIS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F1B"},3868:{"value":"0F1C","name":"TIBETAN SIGN RDEL DKAR GSUM","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F1C"},3869:{"value":"0F1D","name":"TIBETAN SIGN RDEL NAG GCIG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F1D"},3870:{"value":"0F1E","name":"TIBETAN SIGN RDEL NAG GNYIS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F1E"},3871:{"value":"0F1F","name":"TIBETAN SIGN RDEL DKAR RDEL NAG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F1F"},3892:{"value":"0F34","name":"TIBETAN MARK BSDUS RTAGS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F34"},3894:{"value":"0F36","name":"TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F36"},3896:{"value":"0F38","name":"TIBETAN MARK CHE MGO","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0F38"},4030:{"value":"0FBE","name":"TIBETAN KU RU KHA","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FBE"},4031:{"value":"0FBF","name":"TIBETAN KU RU KHA BZHI MIG CAN","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FBF"},4032:{"value":"0FC0","name":"TIBETAN CANTILLATION SIGN HEAVY BEAT","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FC0"},4033:{"value":"0FC1","name":"TIBETAN CANTILLATION SIGN LIGHT BEAT","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FC1"},4034:{"value":"0FC2","name":"TIBETAN CANTILLATION SIGN CANG TE-U","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FC2"},4035:{"value":"0FC3","name":"TIBETAN CANTILLATION SIGN SBUB -CHAL","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FC3"},4036:{"value":"0FC4","name":"TIBETAN SYMBOL DRIL BU","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FC4"},4037:{"value":"0FC5","name":"TIBETAN SYMBOL RDO RJE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FC5"},4039:{"value":"0FC7","name":"TIBETAN SYMBOL RDO RJE RGYA GRAM","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FC7"},4040:{"value":"0FC8","name":"TIBETAN SYMBOL PHUR PA","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FC8"},4041:{"value":"0FC9","name":"TIBETAN SYMBOL NOR BU","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FC9"},4042:{"value":"0FCA","name":"TIBETAN SYMBOL NOR BU NYIS -KHYIL","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FCA"},4043:{"value":"0FCB","name":"TIBETAN SYMBOL NOR BU GSUM -KHYIL","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FCB"},4044:{"value":"0FCC","name":"TIBETAN SYMBOL NOR BU BZHI -KHYIL","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FCC"},4046:{"value":"0FCE","name":"TIBETAN SIGN RDEL NAG RDEL DKAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FCE"},4047:{"value":"0FCF","name":"TIBETAN SIGN RDEL NAG GSUM","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FCF"},4053:{"value":"0FD5","name":"RIGHT-FACING SVASTI SIGN","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FD5"},4054:{"value":"0FD6","name":"LEFT-FACING SVASTI SIGN","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FD6"},4055:{"value":"0FD7","name":"RIGHT-FACING SVASTI SIGN WITH DOTS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FD7"},4056:{"value":"0FD8","name":"LEFT-FACING SVASTI SIGN WITH DOTS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u0FD8"},4254:{"value":"109E","name":"MYANMAR SYMBOL SHAN ONE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u109E"},4255:{"value":"109F","name":"MYANMAR SYMBOL SHAN EXCLAMATION","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u109F"},5008:{"value":"1390","name":"ETHIOPIC TONAL MARK YIZET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1390"},5009:{"value":"1391","name":"ETHIOPIC TONAL MARK DERET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1391"},5010:{"value":"1392","name":"ETHIOPIC TONAL MARK RIKRIK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1392"},5011:{"value":"1393","name":"ETHIOPIC TONAL MARK SHORT RIKRIK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1393"},5012:{"value":"1394","name":"ETHIOPIC TONAL MARK DIFAT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1394"},5013:{"value":"1395","name":"ETHIOPIC TONAL MARK KENAT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1395"},5014:{"value":"1396","name":"ETHIOPIC TONAL MARK CHIRET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1396"},5015:{"value":"1397","name":"ETHIOPIC TONAL MARK HIDET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1397"},5016:{"value":"1398","name":"ETHIOPIC TONAL MARK DERET-HIDET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1398"},5017:{"value":"1399","name":"ETHIOPIC TONAL MARK KURT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1399"},5741:{"value":"166D","name":"CANADIAN SYLLABICS CHI SIGN","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u166D"},6464:{"value":"1940","name":"LIMBU SIGN LOO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1940"},6622:{"value":"19DE","name":"NEW TAI LUE SIGN LAE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19DE"},6623:{"value":"19DF","name":"NEW TAI LUE SIGN LAEV","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19DF"},6624:{"value":"19E0","name":"KHMER SYMBOL PATHAMASAT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19E0"},6625:{"value":"19E1","name":"KHMER SYMBOL MUOY KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19E1"},6626:{"value":"19E2","name":"KHMER SYMBOL PII KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19E2"},6627:{"value":"19E3","name":"KHMER SYMBOL BEI KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19E3"},6628:{"value":"19E4","name":"KHMER SYMBOL BUON KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19E4"},6629:{"value":"19E5","name":"KHMER SYMBOL PRAM KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19E5"},6630:{"value":"19E6","name":"KHMER SYMBOL PRAM-MUOY KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19E6"},6631:{"value":"19E7","name":"KHMER SYMBOL PRAM-PII KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19E7"},6632:{"value":"19E8","name":"KHMER SYMBOL PRAM-BEI KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19E8"},6633:{"value":"19E9","name":"KHMER SYMBOL PRAM-BUON KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19E9"},6634:{"value":"19EA","name":"KHMER SYMBOL DAP KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19EA"},6635:{"value":"19EB","name":"KHMER SYMBOL DAP-MUOY KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19EB"},6636:{"value":"19EC","name":"KHMER SYMBOL DAP-PII KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19EC"},6637:{"value":"19ED","name":"KHMER SYMBOL DAP-BEI KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19ED"},6638:{"value":"19EE","name":"KHMER SYMBOL DAP-BUON KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19EE"},6639:{"value":"19EF","name":"KHMER SYMBOL DAP-PRAM KOET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19EF"},6640:{"value":"19F0","name":"KHMER SYMBOL TUTEYASAT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19F0"},6641:{"value":"19F1","name":"KHMER SYMBOL MUOY ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19F1"},6642:{"value":"19F2","name":"KHMER SYMBOL PII ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19F2"},6643:{"value":"19F3","name":"KHMER SYMBOL BEI ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19F3"},6644:{"value":"19F4","name":"KHMER SYMBOL BUON ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19F4"},6645:{"value":"19F5","name":"KHMER SYMBOL PRAM ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19F5"},6646:{"value":"19F6","name":"KHMER SYMBOL PRAM-MUOY ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19F6"},6647:{"value":"19F7","name":"KHMER SYMBOL PRAM-PII ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19F7"},6648:{"value":"19F8","name":"KHMER SYMBOL PRAM-BEI ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19F8"},6649:{"value":"19F9","name":"KHMER SYMBOL PRAM-BUON ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19F9"},6650:{"value":"19FA","name":"KHMER SYMBOL DAP ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19FA"},6651:{"value":"19FB","name":"KHMER SYMBOL DAP-MUOY ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19FB"},6652:{"value":"19FC","name":"KHMER SYMBOL DAP-PII ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19FC"},6653:{"value":"19FD","name":"KHMER SYMBOL DAP-BEI ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19FD"},6654:{"value":"19FE","name":"KHMER SYMBOL DAP-BUON ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19FE"},6655:{"value":"19FF","name":"KHMER SYMBOL DAP-PRAM ROC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u19FF"},7009:{"value":"1B61","name":"BALINESE MUSICAL SYMBOL DONG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B61"},7010:{"value":"1B62","name":"BALINESE MUSICAL SYMBOL DENG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B62"},7011:{"value":"1B63","name":"BALINESE MUSICAL SYMBOL DUNG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B63"},7012:{"value":"1B64","name":"BALINESE MUSICAL SYMBOL DANG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B64"},7013:{"value":"1B65","name":"BALINESE MUSICAL SYMBOL DANG SURANG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B65"},7014:{"value":"1B66","name":"BALINESE MUSICAL SYMBOL DING","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B66"},7015:{"value":"1B67","name":"BALINESE MUSICAL SYMBOL DAENG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B67"},7016:{"value":"1B68","name":"BALINESE MUSICAL SYMBOL DEUNG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B68"},7017:{"value":"1B69","name":"BALINESE MUSICAL SYMBOL DAING","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B69"},7018:{"value":"1B6A","name":"BALINESE MUSICAL SYMBOL DANG GEDE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B6A"},7028:{"value":"1B74","name":"BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B74"},7029:{"value":"1B75","name":"BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DAG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B75"},7030:{"value":"1B76","name":"BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TUK","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B76"},7031:{"value":"1B77","name":"BALINESE MUSICAL SYMBOL RIGHT-HAND CLOSED TAK","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B77"},7032:{"value":"1B78","name":"BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PANG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B78"},7033:{"value":"1B79","name":"BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PUNG","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B79"},7034:{"value":"1B7A","name":"BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLAK","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B7A"},7035:{"value":"1B7B","name":"BALINESE MUSICAL SYMBOL LEFT-HAND CLOSED PLUK","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B7B"},7036:{"value":"1B7C","name":"BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u1B7C"},8448:{"value":"2100","name":"ACCOUNT OF","category":"So","class":"0","bidirectional_category":"ON","mapping":" 0061 002F 0063","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2100"},8449:{"value":"2101","name":"ADDRESSED TO THE SUBJECT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 0061 002F 0073","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2101"},8451:{"value":"2103","name":"DEGREE CELSIUS","category":"So","class":"0","bidirectional_category":"ON","mapping":" 00B0 0043","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DEGREES CENTIGRADE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2103"},8452:{"value":"2104","name":"CENTRE LINE SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"C L SYMBOL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2104"},8453:{"value":"2105","name":"CARE OF","category":"So","class":"0","bidirectional_category":"ON","mapping":" 0063 002F 006F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2105"},8454:{"value":"2106","name":"CADA UNA","category":"So","class":"0","bidirectional_category":"ON","mapping":" 0063 002F 0075","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2106"},8456:{"value":"2108","name":"SCRUPLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2108"},8457:{"value":"2109","name":"DEGREE FAHRENHEIT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 00B0 0046","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DEGREES FAHRENHEIT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2109"},8468:{"value":"2114","name":"L B BAR SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2114"},8470:{"value":"2116","name":"NUMERO SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 004E 006F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"NUMERO","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2116"},8471:{"value":"2117","name":"SOUND RECORDING COPYRIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2117"},8478:{"value":"211E","name":"PRESCRIPTION TAKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u211E"},8479:{"value":"211F","name":"RESPONSE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u211F"},8480:{"value":"2120","name":"SERVICE MARK","category":"So","class":"0","bidirectional_category":"ON","mapping":" 0053 004D","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2120"},8481:{"value":"2121","name":"TELEPHONE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 0054 0045 004C","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"T E L SYMBOL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2121"},8482:{"value":"2122","name":"TRADE MARK SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 0054 004D","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"TRADEMARK","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2122"},8483:{"value":"2123","name":"VERSICLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2123"},8485:{"value":"2125","name":"OUNCE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"OUNCE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2125"},8487:{"value":"2127","name":"INVERTED OHM SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"MHO","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2127"},8489:{"value":"2129","name":"TURNED GREEK SMALL LETTER IOTA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2129"},8494:{"value":"212E","name":"ESTIMATED SYMBOL","category":"So","class":"0","bidirectional_category":"ET","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u212E"},8506:{"value":"213A","name":"ROTATED CAPITAL Q","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u213A"},8507:{"value":"213B","name":"FACSIMILE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 0046 0041 0058","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u213B"},8522:{"value":"214A","name":"PROPERTY LINE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u214A"},8524:{"value":"214C","name":"PER SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u214C"},8525:{"value":"214D","name":"AKTIESELSKAB","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u214D"},8527:{"value":"214F","name":"SYMBOL FOR SAMARITAN SOURCE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u214F"},8586:{"value":"218A","name":"TURNED DIGIT TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u218A"},8587:{"value":"218B","name":"TURNED DIGIT THREE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u218B"},8597:{"value":"2195","name":"UP DOWN ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2195"},8598:{"value":"2196","name":"NORTH WEST ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UPPER LEFT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2196"},8599:{"value":"2197","name":"NORTH EAST ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UPPER RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2197"},8600:{"value":"2198","name":"SOUTH EAST ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LOWER RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2198"},8601:{"value":"2199","name":"SOUTH WEST ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LOWER LEFT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2199"},8604:{"value":"219C","name":"LEFTWARDS WAVE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT WAVE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u219C"},8605:{"value":"219D","name":"RIGHTWARDS WAVE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT WAVE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u219D"},8606:{"value":"219E","name":"LEFTWARDS TWO HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT TWO HEADED ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u219E"},8607:{"value":"219F","name":"UPWARDS TWO HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP TWO HEADED ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u219F"},8609:{"value":"21A1","name":"DOWNWARDS TWO HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN TWO HEADED ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21A1"},8610:{"value":"21A2","name":"LEFTWARDS ARROW WITH TAIL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT ARROW WITH TAIL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21A2"},8612:{"value":"21A4","name":"LEFTWARDS ARROW FROM BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT ARROW FROM BAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21A4"},8613:{"value":"21A5","name":"UPWARDS ARROW FROM BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP ARROW FROM BAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21A5"},8615:{"value":"21A7","name":"DOWNWARDS ARROW FROM BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN ARROW FROM BAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21A7"},8616:{"value":"21A8","name":"UP DOWN ARROW WITH BASE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21A8"},8617:{"value":"21A9","name":"LEFTWARDS ARROW WITH HOOK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT ARROW WITH HOOK","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21A9"},8618:{"value":"21AA","name":"RIGHTWARDS ARROW WITH HOOK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT ARROW WITH HOOK","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21AA"},8619:{"value":"21AB","name":"LEFTWARDS ARROW WITH LOOP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT ARROW WITH LOOP","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21AB"},8620:{"value":"21AC","name":"RIGHTWARDS ARROW WITH LOOP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT ARROW WITH LOOP","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21AC"},8621:{"value":"21AD","name":"LEFT RIGHT WAVE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21AD"},8623:{"value":"21AF","name":"DOWNWARDS ZIGZAG ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN ZIGZAG ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21AF"},8624:{"value":"21B0","name":"UPWARDS ARROW WITH TIP LEFTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP ARROW WITH TIP LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21B0"},8625:{"value":"21B1","name":"UPWARDS ARROW WITH TIP RIGHTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP ARROW WITH TIP RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21B1"},8626:{"value":"21B2","name":"DOWNWARDS ARROW WITH TIP LEFTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN ARROW WITH TIP LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21B2"},8627:{"value":"21B3","name":"DOWNWARDS ARROW WITH TIP RIGHTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN ARROW WITH TIP RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21B3"},8628:{"value":"21B4","name":"RIGHTWARDS ARROW WITH CORNER DOWNWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT ARROW WITH CORNER DOWN","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21B4"},8629:{"value":"21B5","name":"DOWNWARDS ARROW WITH CORNER LEFTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN ARROW WITH CORNER LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21B5"},8630:{"value":"21B6","name":"ANTICLOCKWISE TOP SEMICIRCLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21B6"},8631:{"value":"21B7","name":"CLOCKWISE TOP SEMICIRCLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21B7"},8632:{"value":"21B8","name":"NORTH WEST ARROW TO LONG BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UPPER LEFT ARROW TO LONG BAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21B8"},8633:{"value":"21B9","name":"LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT ARROW TO BAR OVER RIGHT ARROW TO BAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21B9"},8634:{"value":"21BA","name":"ANTICLOCKWISE OPEN CIRCLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21BA"},8635:{"value":"21BB","name":"CLOCKWISE OPEN CIRCLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21BB"},8636:{"value":"21BC","name":"LEFTWARDS HARPOON WITH BARB UPWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT HARPOON WITH BARB UP","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21BC"},8637:{"value":"21BD","name":"LEFTWARDS HARPOON WITH BARB DOWNWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT HARPOON WITH BARB DOWN","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21BD"},8638:{"value":"21BE","name":"UPWARDS HARPOON WITH BARB RIGHTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP HARPOON WITH BARB RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21BE"},8639:{"value":"21BF","name":"UPWARDS HARPOON WITH BARB LEFTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP HARPOON WITH BARB LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21BF"},8640:{"value":"21C0","name":"RIGHTWARDS HARPOON WITH BARB UPWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT HARPOON WITH BARB UP","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21C0"},8641:{"value":"21C1","name":"RIGHTWARDS HARPOON WITH BARB DOWNWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT HARPOON WITH BARB DOWN","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21C1"},8642:{"value":"21C2","name":"DOWNWARDS HARPOON WITH BARB RIGHTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN HARPOON WITH BARB RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21C2"},8643:{"value":"21C3","name":"DOWNWARDS HARPOON WITH BARB LEFTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN HARPOON WITH BARB LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21C3"},8644:{"value":"21C4","name":"RIGHTWARDS ARROW OVER LEFTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT ARROW OVER LEFT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21C4"},8645:{"value":"21C5","name":"UPWARDS ARROW LEFTWARDS OF DOWNWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP ARROW LEFT OF DOWN ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21C5"},8646:{"value":"21C6","name":"LEFTWARDS ARROW OVER RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT ARROW OVER RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21C6"},8647:{"value":"21C7","name":"LEFTWARDS PAIRED ARROWS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT PAIRED ARROWS","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21C7"},8648:{"value":"21C8","name":"UPWARDS PAIRED ARROWS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP PAIRED ARROWS","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21C8"},8649:{"value":"21C9","name":"RIGHTWARDS PAIRED ARROWS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT PAIRED ARROWS","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21C9"},8650:{"value":"21CA","name":"DOWNWARDS PAIRED ARROWS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN PAIRED ARROWS","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21CA"},8651:{"value":"21CB","name":"LEFTWARDS HARPOON OVER RIGHTWARDS HARPOON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT HARPOON OVER RIGHT HARPOON","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21CB"},8652:{"value":"21CC","name":"RIGHTWARDS HARPOON OVER LEFTWARDS HARPOON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT HARPOON OVER LEFT HARPOON","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21CC"},8653:{"value":"21CD","name":"LEFTWARDS DOUBLE ARROW WITH STROKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"21D0 0338","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT DOUBLE ARROW WITH STROKE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21CD"},8656:{"value":"21D0","name":"LEFTWARDS DOUBLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT DOUBLE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21D0"},8657:{"value":"21D1","name":"UPWARDS DOUBLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP DOUBLE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21D1"},8659:{"value":"21D3","name":"DOWNWARDS DOUBLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN DOUBLE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21D3"},8661:{"value":"21D5","name":"UP DOWN DOUBLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21D5"},8662:{"value":"21D6","name":"NORTH WEST DOUBLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UPPER LEFT DOUBLE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21D6"},8663:{"value":"21D7","name":"NORTH EAST DOUBLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UPPER RIGHT DOUBLE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21D7"},8664:{"value":"21D8","name":"SOUTH EAST DOUBLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LOWER RIGHT DOUBLE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21D8"},8665:{"value":"21D9","name":"SOUTH WEST DOUBLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LOWER LEFT DOUBLE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21D9"},8666:{"value":"21DA","name":"LEFTWARDS TRIPLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT TRIPLE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21DA"},8667:{"value":"21DB","name":"RIGHTWARDS TRIPLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT TRIPLE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21DB"},8668:{"value":"21DC","name":"LEFTWARDS SQUIGGLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT SQUIGGLE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21DC"},8669:{"value":"21DD","name":"RIGHTWARDS SQUIGGLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT SQUIGGLE ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21DD"},8670:{"value":"21DE","name":"UPWARDS ARROW WITH DOUBLE STROKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP ARROW WITH DOUBLE STROKE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21DE"},8671:{"value":"21DF","name":"DOWNWARDS ARROW WITH DOUBLE STROKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN ARROW WITH DOUBLE STROKE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21DF"},8672:{"value":"21E0","name":"LEFTWARDS DASHED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT DASHED ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21E0"},8673:{"value":"21E1","name":"UPWARDS DASHED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP DASHED ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21E1"},8674:{"value":"21E2","name":"RIGHTWARDS DASHED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT DASHED ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21E2"},8675:{"value":"21E3","name":"DOWNWARDS DASHED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DOWN DASHED ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21E3"},8676:{"value":"21E4","name":"LEFTWARDS ARROW TO BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT ARROW TO BAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21E4"},8677:{"value":"21E5","name":"RIGHTWARDS ARROW TO BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT ARROW TO BAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21E5"},8678:{"value":"21E6","name":"LEFTWARDS WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE LEFT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21E6"},8679:{"value":"21E7","name":"UPWARDS WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE UP ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21E7"},8680:{"value":"21E8","name":"RIGHTWARDS WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21E8"},8681:{"value":"21E9","name":"DOWNWARDS WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE DOWN ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21E9"},8682:{"value":"21EA","name":"UPWARDS WHITE ARROW FROM BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE UP ARROW FROM BAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21EA"},8683:{"value":"21EB","name":"UPWARDS WHITE ARROW ON PEDESTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21EB"},8684:{"value":"21EC","name":"UPWARDS WHITE ARROW ON PEDESTAL WITH HORIZONTAL BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21EC"},8685:{"value":"21ED","name":"UPWARDS WHITE ARROW ON PEDESTAL WITH VERTICAL BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21ED"},8686:{"value":"21EE","name":"UPWARDS WHITE DOUBLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21EE"},8687:{"value":"21EF","name":"UPWARDS WHITE DOUBLE ARROW ON PEDESTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21EF"},8688:{"value":"21F0","name":"RIGHTWARDS WHITE ARROW FROM WALL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21F0"},8689:{"value":"21F1","name":"NORTH WEST ARROW TO CORNER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21F1"},8690:{"value":"21F2","name":"SOUTH EAST ARROW TO CORNER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21F2"},8691:{"value":"21F3","name":"UP DOWN WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u21F3"},8960:{"value":"2300","name":"DIAMETER SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2300"},8961:{"value":"2301","name":"ELECTRIC ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2301"},8962:{"value":"2302","name":"HOUSE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2302"},8963:{"value":"2303","name":"UP ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2303"},8964:{"value":"2304","name":"DOWN ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2304"},8965:{"value":"2305","name":"PROJECTIVE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2305"},8966:{"value":"2306","name":"PERSPECTIVE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2306"},8967:{"value":"2307","name":"WAVY LINE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2307"},8972:{"value":"230C","name":"BOTTOM RIGHT CROP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u230C"},8973:{"value":"230D","name":"BOTTOM LEFT CROP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u230D"},8974:{"value":"230E","name":"TOP RIGHT CROP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u230E"},8975:{"value":"230F","name":"TOP LEFT CROP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u230F"},8976:{"value":"2310","name":"REVERSED NOT SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2310"},8977:{"value":"2311","name":"SQUARE LOZENGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2311"},8978:{"value":"2312","name":"ARC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2312"},8979:{"value":"2313","name":"SEGMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2313"},8980:{"value":"2314","name":"SECTOR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2314"},8981:{"value":"2315","name":"TELEPHONE RECORDER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2315"},8982:{"value":"2316","name":"POSITION INDICATOR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2316"},8983:{"value":"2317","name":"VIEWDATA SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2317"},8984:{"value":"2318","name":"PLACE OF INTEREST SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"COMMAND KEY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2318"},8985:{"value":"2319","name":"TURNED NOT SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2319"},8986:{"value":"231A","name":"WATCH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u231A"},8987:{"value":"231B","name":"HOURGLASS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u231B"},8988:{"value":"231C","name":"TOP LEFT CORNER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u231C"},8989:{"value":"231D","name":"TOP RIGHT CORNER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u231D"},8990:{"value":"231E","name":"BOTTOM LEFT CORNER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u231E"},8991:{"value":"231F","name":"BOTTOM RIGHT CORNER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u231F"},8994:{"value":"2322","name":"FROWN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2322"},8995:{"value":"2323","name":"SMILE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2323"},8996:{"value":"2324","name":"UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"ENTER KEY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2324"},8997:{"value":"2325","name":"OPTION KEY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2325"},8998:{"value":"2326","name":"ERASE TO THE RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DELETE TO THE RIGHT KEY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2326"},8999:{"value":"2327","name":"X IN A RECTANGLE BOX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"CLEAR KEY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2327"},9000:{"value":"2328","name":"KEYBOARD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2328"},9003:{"value":"232B","name":"ERASE TO THE LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DELETE TO THE LEFT KEY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u232B"},9004:{"value":"232C","name":"BENZENE RING","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u232C"},9005:{"value":"232D","name":"CYLINDRICITY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u232D"},9006:{"value":"232E","name":"ALL AROUND-PROFILE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u232E"},9007:{"value":"232F","name":"SYMMETRY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u232F"},9008:{"value":"2330","name":"TOTAL RUNOUT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2330"},9009:{"value":"2331","name":"DIMENSION ORIGIN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2331"},9010:{"value":"2332","name":"CONICAL TAPER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2332"},9011:{"value":"2333","name":"SLOPE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2333"},9012:{"value":"2334","name":"COUNTERBORE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2334"},9013:{"value":"2335","name":"COUNTERSINK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2335"},9014:{"value":"2336","name":"APL FUNCTIONAL SYMBOL I-BEAM","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2336"},9015:{"value":"2337","name":"APL FUNCTIONAL SYMBOL SQUISH QUAD","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2337"},9016:{"value":"2338","name":"APL FUNCTIONAL SYMBOL QUAD EQUAL","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2338"},9017:{"value":"2339","name":"APL FUNCTIONAL SYMBOL QUAD DIVIDE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2339"},9018:{"value":"233A","name":"APL FUNCTIONAL SYMBOL QUAD DIAMOND","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u233A"},9019:{"value":"233B","name":"APL FUNCTIONAL SYMBOL QUAD JOT","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u233B"},9020:{"value":"233C","name":"APL FUNCTIONAL SYMBOL QUAD CIRCLE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u233C"},9021:{"value":"233D","name":"APL FUNCTIONAL SYMBOL CIRCLE STILE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u233D"},9022:{"value":"233E","name":"APL FUNCTIONAL SYMBOL CIRCLE JOT","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u233E"},9023:{"value":"233F","name":"APL FUNCTIONAL SYMBOL SLASH BAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u233F"},9024:{"value":"2340","name":"APL FUNCTIONAL SYMBOL BACKSLASH BAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2340"},9025:{"value":"2341","name":"APL FUNCTIONAL SYMBOL QUAD SLASH","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2341"},9026:{"value":"2342","name":"APL FUNCTIONAL SYMBOL QUAD BACKSLASH","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2342"},9027:{"value":"2343","name":"APL FUNCTIONAL SYMBOL QUAD LESS-THAN","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2343"},9028:{"value":"2344","name":"APL FUNCTIONAL SYMBOL QUAD GREATER-THAN","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2344"},9029:{"value":"2345","name":"APL FUNCTIONAL SYMBOL LEFTWARDS VANE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2345"},9030:{"value":"2346","name":"APL FUNCTIONAL SYMBOL RIGHTWARDS VANE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2346"},9031:{"value":"2347","name":"APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2347"},9032:{"value":"2348","name":"APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2348"},9033:{"value":"2349","name":"APL FUNCTIONAL SYMBOL CIRCLE BACKSLASH","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2349"},9034:{"value":"234A","name":"APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u234A"},9035:{"value":"234B","name":"APL FUNCTIONAL SYMBOL DELTA STILE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u234B"},9036:{"value":"234C","name":"APL FUNCTIONAL SYMBOL QUAD DOWN CARET","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u234C"},9037:{"value":"234D","name":"APL FUNCTIONAL SYMBOL QUAD DELTA","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u234D"},9038:{"value":"234E","name":"APL FUNCTIONAL SYMBOL DOWN TACK JOT","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u234E"},9039:{"value":"234F","name":"APL FUNCTIONAL SYMBOL UPWARDS VANE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u234F"},9040:{"value":"2350","name":"APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2350"},9041:{"value":"2351","name":"APL FUNCTIONAL SYMBOL UP TACK OVERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2351"},9042:{"value":"2352","name":"APL FUNCTIONAL SYMBOL DEL STILE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2352"},9043:{"value":"2353","name":"APL FUNCTIONAL SYMBOL QUAD UP CARET","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2353"},9044:{"value":"2354","name":"APL FUNCTIONAL SYMBOL QUAD DEL","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2354"},9045:{"value":"2355","name":"APL FUNCTIONAL SYMBOL UP TACK JOT","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2355"},9046:{"value":"2356","name":"APL FUNCTIONAL SYMBOL DOWNWARDS VANE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2356"},9047:{"value":"2357","name":"APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2357"},9048:{"value":"2358","name":"APL FUNCTIONAL SYMBOL QUOTE UNDERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2358"},9049:{"value":"2359","name":"APL FUNCTIONAL SYMBOL DELTA UNDERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2359"},9050:{"value":"235A","name":"APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u235A"},9051:{"value":"235B","name":"APL FUNCTIONAL SYMBOL JOT UNDERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u235B"},9052:{"value":"235C","name":"APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u235C"},9053:{"value":"235D","name":"APL FUNCTIONAL SYMBOL UP SHOE JOT","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u235D"},9054:{"value":"235E","name":"APL FUNCTIONAL SYMBOL QUOTE QUAD","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u235E"},9055:{"value":"235F","name":"APL FUNCTIONAL SYMBOL CIRCLE STAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u235F"},9056:{"value":"2360","name":"APL FUNCTIONAL SYMBOL QUAD COLON","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2360"},9057:{"value":"2361","name":"APL FUNCTIONAL SYMBOL UP TACK DIAERESIS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2361"},9058:{"value":"2362","name":"APL FUNCTIONAL SYMBOL DEL DIAERESIS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2362"},9059:{"value":"2363","name":"APL FUNCTIONAL SYMBOL STAR DIAERESIS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2363"},9060:{"value":"2364","name":"APL FUNCTIONAL SYMBOL JOT DIAERESIS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2364"},9061:{"value":"2365","name":"APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2365"},9062:{"value":"2366","name":"APL FUNCTIONAL SYMBOL DOWN SHOE STILE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2366"},9063:{"value":"2367","name":"APL FUNCTIONAL SYMBOL LEFT SHOE STILE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2367"},9064:{"value":"2368","name":"APL FUNCTIONAL SYMBOL TILDE DIAERESIS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2368"},9065:{"value":"2369","name":"APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2369"},9066:{"value":"236A","name":"APL FUNCTIONAL SYMBOL COMMA BAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u236A"},9067:{"value":"236B","name":"APL FUNCTIONAL SYMBOL DEL TILDE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u236B"},9068:{"value":"236C","name":"APL FUNCTIONAL SYMBOL ZILDE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u236C"},9069:{"value":"236D","name":"APL FUNCTIONAL SYMBOL STILE TILDE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u236D"},9070:{"value":"236E","name":"APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u236E"},9071:{"value":"236F","name":"APL FUNCTIONAL SYMBOL QUAD NOT EQUAL","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u236F"},9072:{"value":"2370","name":"APL FUNCTIONAL SYMBOL QUAD QUESTION","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2370"},9073:{"value":"2371","name":"APL FUNCTIONAL SYMBOL DOWN CARET TILDE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2371"},9074:{"value":"2372","name":"APL FUNCTIONAL SYMBOL UP CARET TILDE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2372"},9075:{"value":"2373","name":"APL FUNCTIONAL SYMBOL IOTA","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2373"},9076:{"value":"2374","name":"APL FUNCTIONAL SYMBOL RHO","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2374"},9077:{"value":"2375","name":"APL FUNCTIONAL SYMBOL OMEGA","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2375"},9078:{"value":"2376","name":"APL FUNCTIONAL SYMBOL ALPHA UNDERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2376"},9079:{"value":"2377","name":"APL FUNCTIONAL SYMBOL EPSILON UNDERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2377"},9080:{"value":"2378","name":"APL FUNCTIONAL SYMBOL IOTA UNDERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2378"},9081:{"value":"2379","name":"APL FUNCTIONAL SYMBOL OMEGA UNDERBAR","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2379"},9082:{"value":"237A","name":"APL FUNCTIONAL SYMBOL ALPHA","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u237A"},9083:{"value":"237B","name":"NOT CHECK MARK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u237B"},9085:{"value":"237D","name":"SHOULDERED OPEN BOX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u237D"},9086:{"value":"237E","name":"BELL SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u237E"},9087:{"value":"237F","name":"VERTICAL LINE WITH MIDDLE DOT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u237F"},9088:{"value":"2380","name":"INSERTION SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2380"},9089:{"value":"2381","name":"CONTINUOUS UNDERLINE SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2381"},9090:{"value":"2382","name":"DISCONTINUOUS UNDERLINE SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2382"},9091:{"value":"2383","name":"EMPHASIS SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2383"},9092:{"value":"2384","name":"COMPOSITION SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2384"},9093:{"value":"2385","name":"WHITE SQUARE WITH CENTRE VERTICAL LINE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2385"},9094:{"value":"2386","name":"ENTER SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2386"},9095:{"value":"2387","name":"ALTERNATIVE KEY SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2387"},9096:{"value":"2388","name":"HELM SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2388"},9097:{"value":"2389","name":"CIRCLED HORIZONTAL BAR WITH NOTCH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2389"},9098:{"value":"238A","name":"CIRCLED TRIANGLE DOWN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u238A"},9099:{"value":"238B","name":"BROKEN CIRCLE WITH NORTHWEST ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u238B"},9100:{"value":"238C","name":"UNDO SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u238C"},9101:{"value":"238D","name":"MONOSTABLE SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u238D"},9102:{"value":"238E","name":"HYSTERESIS SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u238E"},9103:{"value":"238F","name":"OPEN-CIRCUIT-OUTPUT H-TYPE SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u238F"},9104:{"value":"2390","name":"OPEN-CIRCUIT-OUTPUT L-TYPE SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2390"},9105:{"value":"2391","name":"PASSIVE-PULL-DOWN-OUTPUT SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2391"},9106:{"value":"2392","name":"PASSIVE-PULL-UP-OUTPUT SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2392"},9107:{"value":"2393","name":"DIRECT CURRENT SYMBOL FORM TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2393"},9108:{"value":"2394","name":"SOFTWARE-FUNCTION SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2394"},9109:{"value":"2395","name":"APL FUNCTIONAL SYMBOL QUAD","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2395"},9110:{"value":"2396","name":"DECIMAL SEPARATOR KEY SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2396"},9111:{"value":"2397","name":"PREVIOUS PAGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2397"},9112:{"value":"2398","name":"NEXT PAGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2398"},9113:{"value":"2399","name":"PRINT SCREEN SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2399"},9114:{"value":"239A","name":"CLEAR SCREEN SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u239A"},9140:{"value":"23B4","name":"TOP SQUARE BRACKET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23B4"},9141:{"value":"23B5","name":"BOTTOM SQUARE BRACKET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23B5"},9142:{"value":"23B6","name":"BOTTOM SQUARE BRACKET OVER TOP SQUARE BRACKET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23B6"},9143:{"value":"23B7","name":"RADICAL SYMBOL BOTTOM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23B7"},9144:{"value":"23B8","name":"LEFT VERTICAL BOX LINE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23B8"},9145:{"value":"23B9","name":"RIGHT VERTICAL BOX LINE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23B9"},9146:{"value":"23BA","name":"HORIZONTAL SCAN LINE-1","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23BA"},9147:{"value":"23BB","name":"HORIZONTAL SCAN LINE-3","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23BB"},9148:{"value":"23BC","name":"HORIZONTAL SCAN LINE-7","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23BC"},9149:{"value":"23BD","name":"HORIZONTAL SCAN LINE-9","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23BD"},9150:{"value":"23BE","name":"DENTISTRY SYMBOL LIGHT VERTICAL AND TOP RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23BE"},9151:{"value":"23BF","name":"DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23BF"},9152:{"value":"23C0","name":"DENTISTRY SYMBOL LIGHT VERTICAL WITH CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23C0"},9153:{"value":"23C1","name":"DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23C1"},9154:{"value":"23C2","name":"DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23C2"},9155:{"value":"23C3","name":"DENTISTRY SYMBOL LIGHT VERTICAL WITH TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23C3"},9156:{"value":"23C4","name":"DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23C4"},9157:{"value":"23C5","name":"DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23C5"},9158:{"value":"23C6","name":"DENTISTRY SYMBOL LIGHT VERTICAL AND WAVE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23C6"},9159:{"value":"23C7","name":"DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL WITH WAVE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23C7"},9160:{"value":"23C8","name":"DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL WITH WAVE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23C8"},9161:{"value":"23C9","name":"DENTISTRY SYMBOL LIGHT DOWN AND HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23C9"},9162:{"value":"23CA","name":"DENTISTRY SYMBOL LIGHT UP AND HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23CA"},9163:{"value":"23CB","name":"DENTISTRY SYMBOL LIGHT VERTICAL AND TOP LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23CB"},9164:{"value":"23CC","name":"DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23CC"},9165:{"value":"23CD","name":"SQUARE FOOT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23CD"},9166:{"value":"23CE","name":"RETURN SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23CE"},9167:{"value":"23CF","name":"EJECT SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23CF"},9168:{"value":"23D0","name":"VERTICAL LINE EXTENSION","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23D0"},9169:{"value":"23D1","name":"METRICAL BREVE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23D1"},9170:{"value":"23D2","name":"METRICAL LONG OVER SHORT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23D2"},9171:{"value":"23D3","name":"METRICAL SHORT OVER LONG","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23D3"},9172:{"value":"23D4","name":"METRICAL LONG OVER TWO SHORTS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23D4"},9173:{"value":"23D5","name":"METRICAL TWO SHORTS OVER LONG","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23D5"},9174:{"value":"23D6","name":"METRICAL TWO SHORTS JOINED","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23D6"},9175:{"value":"23D7","name":"METRICAL TRISEME","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23D7"},9176:{"value":"23D8","name":"METRICAL TETRASEME","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23D8"},9177:{"value":"23D9","name":"METRICAL PENTASEME","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23D9"},9178:{"value":"23DA","name":"EARTH GROUND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23DA"},9179:{"value":"23DB","name":"FUSE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23DB"},9186:{"value":"23E2","name":"WHITE TRAPEZIUM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23E2"},9187:{"value":"23E3","name":"BENZENE RING WITH CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23E3"},9188:{"value":"23E4","name":"STRAIGHTNESS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23E4"},9189:{"value":"23E5","name":"FLATNESS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23E5"},9190:{"value":"23E6","name":"AC CURRENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23E6"},9191:{"value":"23E7","name":"ELECTRICAL INTERSECTION","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23E7"},9192:{"value":"23E8","name":"DECIMAL EXPONENT SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23E8"},9193:{"value":"23E9","name":"BLACK RIGHT-POINTING DOUBLE TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23E9"},9194:{"value":"23EA","name":"BLACK LEFT-POINTING DOUBLE TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23EA"},9195:{"value":"23EB","name":"BLACK UP-POINTING DOUBLE TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23EB"},9196:{"value":"23EC","name":"BLACK DOWN-POINTING DOUBLE TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23EC"},9197:{"value":"23ED","name":"BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23ED"},9198:{"value":"23EE","name":"BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23EE"},9199:{"value":"23EF","name":"BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23EF"},9200:{"value":"23F0","name":"ALARM CLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23F0"},9201:{"value":"23F1","name":"STOPWATCH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23F1"},9202:{"value":"23F2","name":"TIMER CLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23F2"},9203:{"value":"23F3","name":"HOURGLASS WITH FLOWING SAND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23F3"},9204:{"value":"23F4","name":"BLACK MEDIUM LEFT-POINTING TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23F4"},9205:{"value":"23F5","name":"BLACK MEDIUM RIGHT-POINTING TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23F5"},9206:{"value":"23F6","name":"BLACK MEDIUM UP-POINTING TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23F6"},9207:{"value":"23F7","name":"BLACK MEDIUM DOWN-POINTING TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23F7"},9208:{"value":"23F8","name":"DOUBLE VERTICAL BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23F8"},9209:{"value":"23F9","name":"BLACK SQUARE FOR STOP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23F9"},9210:{"value":"23FA","name":"BLACK CIRCLE FOR RECORD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23FA"},9211:{"value":"23FB","name":"POWER SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23FB"},9212:{"value":"23FC","name":"POWER ON-OFF SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23FC"},9213:{"value":"23FD","name":"POWER ON SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23FD"},9214:{"value":"23FE","name":"POWER SLEEP SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23FE"},9215:{"value":"23FF","name":"OBSERVER EYE SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u23FF"},9216:{"value":"2400","name":"SYMBOL FOR NULL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR NULL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2400"},9217:{"value":"2401","name":"SYMBOL FOR START OF HEADING","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR START OF HEADING","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2401"},9218:{"value":"2402","name":"SYMBOL FOR START OF TEXT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR START OF TEXT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2402"},9219:{"value":"2403","name":"SYMBOL FOR END OF TEXT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR END OF TEXT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2403"},9220:{"value":"2404","name":"SYMBOL FOR END OF TRANSMISSION","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR END OF TRANSMISSION","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2404"},9221:{"value":"2405","name":"SYMBOL FOR ENQUIRY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR ENQUIRY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2405"},9222:{"value":"2406","name":"SYMBOL FOR ACKNOWLEDGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR ACKNOWLEDGE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2406"},9223:{"value":"2407","name":"SYMBOL FOR BELL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR BELL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2407"},9224:{"value":"2408","name":"SYMBOL FOR BACKSPACE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR BACKSPACE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2408"},9225:{"value":"2409","name":"SYMBOL FOR HORIZONTAL TABULATION","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR HORIZONTAL TABULATION","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2409"},9226:{"value":"240A","name":"SYMBOL FOR LINE FEED","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR LINE FEED","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u240A"},9227:{"value":"240B","name":"SYMBOL FOR VERTICAL TABULATION","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR VERTICAL TABULATION","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u240B"},9228:{"value":"240C","name":"SYMBOL FOR FORM FEED","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR FORM FEED","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u240C"},9229:{"value":"240D","name":"SYMBOL FOR CARRIAGE RETURN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR CARRIAGE RETURN","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u240D"},9230:{"value":"240E","name":"SYMBOL FOR SHIFT OUT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR SHIFT OUT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u240E"},9231:{"value":"240F","name":"SYMBOL FOR SHIFT IN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR SHIFT IN","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u240F"},9232:{"value":"2410","name":"SYMBOL FOR DATA LINK ESCAPE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR DATA LINK ESCAPE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2410"},9233:{"value":"2411","name":"SYMBOL FOR DEVICE CONTROL ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR DEVICE CONTROL ONE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2411"},9234:{"value":"2412","name":"SYMBOL FOR DEVICE CONTROL TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR DEVICE CONTROL TWO","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2412"},9235:{"value":"2413","name":"SYMBOL FOR DEVICE CONTROL THREE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR DEVICE CONTROL THREE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2413"},9236:{"value":"2414","name":"SYMBOL FOR DEVICE CONTROL FOUR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR DEVICE CONTROL FOUR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2414"},9237:{"value":"2415","name":"SYMBOL FOR NEGATIVE ACKNOWLEDGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR NEGATIVE ACKNOWLEDGE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2415"},9238:{"value":"2416","name":"SYMBOL FOR SYNCHRONOUS IDLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR SYNCHRONOUS IDLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2416"},9239:{"value":"2417","name":"SYMBOL FOR END OF TRANSMISSION BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR END OF TRANSMISSION BLOCK","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2417"},9240:{"value":"2418","name":"SYMBOL FOR CANCEL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR CANCEL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2418"},9241:{"value":"2419","name":"SYMBOL FOR END OF MEDIUM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR END OF MEDIUM","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2419"},9242:{"value":"241A","name":"SYMBOL FOR SUBSTITUTE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR SUBSTITUTE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u241A"},9243:{"value":"241B","name":"SYMBOL FOR ESCAPE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR ESCAPE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u241B"},9244:{"value":"241C","name":"SYMBOL FOR FILE SEPARATOR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR FILE SEPARATOR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u241C"},9245:{"value":"241D","name":"SYMBOL FOR GROUP SEPARATOR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR GROUP SEPARATOR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u241D"},9246:{"value":"241E","name":"SYMBOL FOR RECORD SEPARATOR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR RECORD SEPARATOR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u241E"},9247:{"value":"241F","name":"SYMBOL FOR UNIT SEPARATOR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR UNIT SEPARATOR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u241F"},9248:{"value":"2420","name":"SYMBOL FOR SPACE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR SPACE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2420"},9249:{"value":"2421","name":"SYMBOL FOR DELETE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR DELETE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2421"},9250:{"value":"2422","name":"BLANK SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLANK","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2422"},9251:{"value":"2423","name":"OPEN BOX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2423"},9252:{"value":"2424","name":"SYMBOL FOR NEWLINE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"GRAPHIC FOR NEWLINE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2424"},9253:{"value":"2425","name":"SYMBOL FOR DELETE FORM TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2425"},9254:{"value":"2426","name":"SYMBOL FOR SUBSTITUTE FORM TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2426"},9280:{"value":"2440","name":"OCR HOOK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2440"},9281:{"value":"2441","name":"OCR CHAIR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2441"},9282:{"value":"2442","name":"OCR FORK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2442"},9283:{"value":"2443","name":"OCR INVERTED FORK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2443"},9284:{"value":"2444","name":"OCR BELT BUCKLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2444"},9285:{"value":"2445","name":"OCR BOW TIE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2445"},9286:{"value":"2446","name":"OCR BRANCH BANK IDENTIFICATION","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2446"},9287:{"value":"2447","name":"OCR AMOUNT OF CHECK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2447"},9288:{"value":"2448","name":"OCR DASH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2448"},9289:{"value":"2449","name":"OCR CUSTOMER ACCOUNT NUMBER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2449"},9290:{"value":"244A","name":"OCR DOUBLE BACKSLASH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u244A"},9372:{"value":"249C","name":"PARENTHESIZED LATIN SMALL LETTER A","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0061 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u249C"},9373:{"value":"249D","name":"PARENTHESIZED LATIN SMALL LETTER B","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0062 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u249D"},9374:{"value":"249E","name":"PARENTHESIZED LATIN SMALL LETTER C","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0063 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u249E"},9375:{"value":"249F","name":"PARENTHESIZED LATIN SMALL LETTER D","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0064 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u249F"},9376:{"value":"24A0","name":"PARENTHESIZED LATIN SMALL LETTER E","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0065 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24A0"},9377:{"value":"24A1","name":"PARENTHESIZED LATIN SMALL LETTER F","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0066 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24A1"},9378:{"value":"24A2","name":"PARENTHESIZED LATIN SMALL LETTER G","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0067 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24A2"},9379:{"value":"24A3","name":"PARENTHESIZED LATIN SMALL LETTER H","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0068 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24A3"},9380:{"value":"24A4","name":"PARENTHESIZED LATIN SMALL LETTER I","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0069 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24A4"},9381:{"value":"24A5","name":"PARENTHESIZED LATIN SMALL LETTER J","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 006A 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24A5"},9382:{"value":"24A6","name":"PARENTHESIZED LATIN SMALL LETTER K","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 006B 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24A6"},9383:{"value":"24A7","name":"PARENTHESIZED LATIN SMALL LETTER L","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 006C 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24A7"},9384:{"value":"24A8","name":"PARENTHESIZED LATIN SMALL LETTER M","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 006D 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24A8"},9385:{"value":"24A9","name":"PARENTHESIZED LATIN SMALL LETTER N","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 006E 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24A9"},9386:{"value":"24AA","name":"PARENTHESIZED LATIN SMALL LETTER O","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 006F 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24AA"},9387:{"value":"24AB","name":"PARENTHESIZED LATIN SMALL LETTER P","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0070 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24AB"},9388:{"value":"24AC","name":"PARENTHESIZED LATIN SMALL LETTER Q","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0071 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24AC"},9389:{"value":"24AD","name":"PARENTHESIZED LATIN SMALL LETTER R","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0072 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24AD"},9390:{"value":"24AE","name":"PARENTHESIZED LATIN SMALL LETTER S","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0073 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24AE"},9391:{"value":"24AF","name":"PARENTHESIZED LATIN SMALL LETTER T","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0074 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24AF"},9392:{"value":"24B0","name":"PARENTHESIZED LATIN SMALL LETTER U","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0075 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24B0"},9393:{"value":"24B1","name":"PARENTHESIZED LATIN SMALL LETTER V","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0076 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24B1"},9394:{"value":"24B2","name":"PARENTHESIZED LATIN SMALL LETTER W","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0077 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24B2"},9395:{"value":"24B3","name":"PARENTHESIZED LATIN SMALL LETTER X","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0078 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24B3"},9396:{"value":"24B4","name":"PARENTHESIZED LATIN SMALL LETTER Y","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 0079 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24B4"},9397:{"value":"24B5","name":"PARENTHESIZED LATIN SMALL LETTER Z","category":"So","class":"0","bidirectional_category":"L","mapping":" 0028 007A 0029","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u24B5"},9398:{"value":"24B6","name":"CIRCLED LATIN CAPITAL LETTER A","category":"So","class":"0","bidirectional_category":"L","mapping":" 0041","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24D0","titlecase_mapping":"","symbol":"\u24B6"},9399:{"value":"24B7","name":"CIRCLED LATIN CAPITAL LETTER B","category":"So","class":"0","bidirectional_category":"L","mapping":" 0042","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24D1","titlecase_mapping":"","symbol":"\u24B7"},9400:{"value":"24B8","name":"CIRCLED LATIN CAPITAL LETTER C","category":"So","class":"0","bidirectional_category":"L","mapping":" 0043","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24D2","titlecase_mapping":"","symbol":"\u24B8"},9401:{"value":"24B9","name":"CIRCLED LATIN CAPITAL LETTER D","category":"So","class":"0","bidirectional_category":"L","mapping":" 0044","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24D3","titlecase_mapping":"","symbol":"\u24B9"},9402:{"value":"24BA","name":"CIRCLED LATIN CAPITAL LETTER E","category":"So","class":"0","bidirectional_category":"L","mapping":" 0045","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24D4","titlecase_mapping":"","symbol":"\u24BA"},9403:{"value":"24BB","name":"CIRCLED LATIN CAPITAL LETTER F","category":"So","class":"0","bidirectional_category":"L","mapping":" 0046","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24D5","titlecase_mapping":"","symbol":"\u24BB"},9404:{"value":"24BC","name":"CIRCLED LATIN CAPITAL LETTER G","category":"So","class":"0","bidirectional_category":"L","mapping":" 0047","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24D6","titlecase_mapping":"","symbol":"\u24BC"},9405:{"value":"24BD","name":"CIRCLED LATIN CAPITAL LETTER H","category":"So","class":"0","bidirectional_category":"L","mapping":" 0048","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24D7","titlecase_mapping":"","symbol":"\u24BD"},9406:{"value":"24BE","name":"CIRCLED LATIN CAPITAL LETTER I","category":"So","class":"0","bidirectional_category":"L","mapping":" 0049","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24D8","titlecase_mapping":"","symbol":"\u24BE"},9407:{"value":"24BF","name":"CIRCLED LATIN CAPITAL LETTER J","category":"So","class":"0","bidirectional_category":"L","mapping":" 004A","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24D9","titlecase_mapping":"","symbol":"\u24BF"},9408:{"value":"24C0","name":"CIRCLED LATIN CAPITAL LETTER K","category":"So","class":"0","bidirectional_category":"L","mapping":" 004B","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24DA","titlecase_mapping":"","symbol":"\u24C0"},9409:{"value":"24C1","name":"CIRCLED LATIN CAPITAL LETTER L","category":"So","class":"0","bidirectional_category":"L","mapping":" 004C","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24DB","titlecase_mapping":"","symbol":"\u24C1"},9410:{"value":"24C2","name":"CIRCLED LATIN CAPITAL LETTER M","category":"So","class":"0","bidirectional_category":"L","mapping":" 004D","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24DC","titlecase_mapping":"","symbol":"\u24C2"},9411:{"value":"24C3","name":"CIRCLED LATIN CAPITAL LETTER N","category":"So","class":"0","bidirectional_category":"L","mapping":" 004E","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24DD","titlecase_mapping":"","symbol":"\u24C3"},9412:{"value":"24C4","name":"CIRCLED LATIN CAPITAL LETTER O","category":"So","class":"0","bidirectional_category":"L","mapping":" 004F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24DE","titlecase_mapping":"","symbol":"\u24C4"},9413:{"value":"24C5","name":"CIRCLED LATIN CAPITAL LETTER P","category":"So","class":"0","bidirectional_category":"L","mapping":" 0050","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24DF","titlecase_mapping":"","symbol":"\u24C5"},9414:{"value":"24C6","name":"CIRCLED LATIN CAPITAL LETTER Q","category":"So","class":"0","bidirectional_category":"L","mapping":" 0051","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24E0","titlecase_mapping":"","symbol":"\u24C6"},9415:{"value":"24C7","name":"CIRCLED LATIN CAPITAL LETTER R","category":"So","class":"0","bidirectional_category":"L","mapping":" 0052","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24E1","titlecase_mapping":"","symbol":"\u24C7"},9416:{"value":"24C8","name":"CIRCLED LATIN CAPITAL LETTER S","category":"So","class":"0","bidirectional_category":"L","mapping":" 0053","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24E2","titlecase_mapping":"","symbol":"\u24C8"},9417:{"value":"24C9","name":"CIRCLED LATIN CAPITAL LETTER T","category":"So","class":"0","bidirectional_category":"L","mapping":" 0054","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24E3","titlecase_mapping":"","symbol":"\u24C9"},9418:{"value":"24CA","name":"CIRCLED LATIN CAPITAL LETTER U","category":"So","class":"0","bidirectional_category":"L","mapping":" 0055","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24E4","titlecase_mapping":"","symbol":"\u24CA"},9419:{"value":"24CB","name":"CIRCLED LATIN CAPITAL LETTER V","category":"So","class":"0","bidirectional_category":"L","mapping":" 0056","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24E5","titlecase_mapping":"","symbol":"\u24CB"},9420:{"value":"24CC","name":"CIRCLED LATIN CAPITAL LETTER W","category":"So","class":"0","bidirectional_category":"L","mapping":" 0057","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24E6","titlecase_mapping":"","symbol":"\u24CC"},9421:{"value":"24CD","name":"CIRCLED LATIN CAPITAL LETTER X","category":"So","class":"0","bidirectional_category":"L","mapping":" 0058","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24E7","titlecase_mapping":"","symbol":"\u24CD"},9422:{"value":"24CE","name":"CIRCLED LATIN CAPITAL LETTER Y","category":"So","class":"0","bidirectional_category":"L","mapping":" 0059","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24E8","titlecase_mapping":"","symbol":"\u24CE"},9423:{"value":"24CF","name":"CIRCLED LATIN CAPITAL LETTER Z","category":"So","class":"0","bidirectional_category":"L","mapping":" 005A","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"24E9","titlecase_mapping":"","symbol":"\u24CF"},9424:{"value":"24D0","name":"CIRCLED LATIN SMALL LETTER A","category":"So","class":"0","bidirectional_category":"L","mapping":" 0061","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24B6","lowercase_mapping":"","titlecase_mapping":"24B6","symbol":"\u24D0"},9425:{"value":"24D1","name":"CIRCLED LATIN SMALL LETTER B","category":"So","class":"0","bidirectional_category":"L","mapping":" 0062","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24B7","lowercase_mapping":"","titlecase_mapping":"24B7","symbol":"\u24D1"},9426:{"value":"24D2","name":"CIRCLED LATIN SMALL LETTER C","category":"So","class":"0","bidirectional_category":"L","mapping":" 0063","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24B8","lowercase_mapping":"","titlecase_mapping":"24B8","symbol":"\u24D2"},9427:{"value":"24D3","name":"CIRCLED LATIN SMALL LETTER D","category":"So","class":"0","bidirectional_category":"L","mapping":" 0064","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24B9","lowercase_mapping":"","titlecase_mapping":"24B9","symbol":"\u24D3"},9428:{"value":"24D4","name":"CIRCLED LATIN SMALL LETTER E","category":"So","class":"0","bidirectional_category":"L","mapping":" 0065","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24BA","lowercase_mapping":"","titlecase_mapping":"24BA","symbol":"\u24D4"},9429:{"value":"24D5","name":"CIRCLED LATIN SMALL LETTER F","category":"So","class":"0","bidirectional_category":"L","mapping":" 0066","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24BB","lowercase_mapping":"","titlecase_mapping":"24BB","symbol":"\u24D5"},9430:{"value":"24D6","name":"CIRCLED LATIN SMALL LETTER G","category":"So","class":"0","bidirectional_category":"L","mapping":" 0067","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24BC","lowercase_mapping":"","titlecase_mapping":"24BC","symbol":"\u24D6"},9431:{"value":"24D7","name":"CIRCLED LATIN SMALL LETTER H","category":"So","class":"0","bidirectional_category":"L","mapping":" 0068","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24BD","lowercase_mapping":"","titlecase_mapping":"24BD","symbol":"\u24D7"},9432:{"value":"24D8","name":"CIRCLED LATIN SMALL LETTER I","category":"So","class":"0","bidirectional_category":"L","mapping":" 0069","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24BE","lowercase_mapping":"","titlecase_mapping":"24BE","symbol":"\u24D8"},9433:{"value":"24D9","name":"CIRCLED LATIN SMALL LETTER J","category":"So","class":"0","bidirectional_category":"L","mapping":" 006A","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24BF","lowercase_mapping":"","titlecase_mapping":"24BF","symbol":"\u24D9"},9434:{"value":"24DA","name":"CIRCLED LATIN SMALL LETTER K","category":"So","class":"0","bidirectional_category":"L","mapping":" 006B","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24C0","lowercase_mapping":"","titlecase_mapping":"24C0","symbol":"\u24DA"},9435:{"value":"24DB","name":"CIRCLED LATIN SMALL LETTER L","category":"So","class":"0","bidirectional_category":"L","mapping":" 006C","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24C1","lowercase_mapping":"","titlecase_mapping":"24C1","symbol":"\u24DB"},9436:{"value":"24DC","name":"CIRCLED LATIN SMALL LETTER M","category":"So","class":"0","bidirectional_category":"L","mapping":" 006D","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24C2","lowercase_mapping":"","titlecase_mapping":"24C2","symbol":"\u24DC"},9437:{"value":"24DD","name":"CIRCLED LATIN SMALL LETTER N","category":"So","class":"0","bidirectional_category":"L","mapping":" 006E","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24C3","lowercase_mapping":"","titlecase_mapping":"24C3","symbol":"\u24DD"},9438:{"value":"24DE","name":"CIRCLED LATIN SMALL LETTER O","category":"So","class":"0","bidirectional_category":"L","mapping":" 006F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24C4","lowercase_mapping":"","titlecase_mapping":"24C4","symbol":"\u24DE"},9439:{"value":"24DF","name":"CIRCLED LATIN SMALL LETTER P","category":"So","class":"0","bidirectional_category":"L","mapping":" 0070","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24C5","lowercase_mapping":"","titlecase_mapping":"24C5","symbol":"\u24DF"},9440:{"value":"24E0","name":"CIRCLED LATIN SMALL LETTER Q","category":"So","class":"0","bidirectional_category":"L","mapping":" 0071","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24C6","lowercase_mapping":"","titlecase_mapping":"24C6","symbol":"\u24E0"},9441:{"value":"24E1","name":"CIRCLED LATIN SMALL LETTER R","category":"So","class":"0","bidirectional_category":"L","mapping":" 0072","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24C7","lowercase_mapping":"","titlecase_mapping":"24C7","symbol":"\u24E1"},9442:{"value":"24E2","name":"CIRCLED LATIN SMALL LETTER S","category":"So","class":"0","bidirectional_category":"L","mapping":" 0073","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24C8","lowercase_mapping":"","titlecase_mapping":"24C8","symbol":"\u24E2"},9443:{"value":"24E3","name":"CIRCLED LATIN SMALL LETTER T","category":"So","class":"0","bidirectional_category":"L","mapping":" 0074","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24C9","lowercase_mapping":"","titlecase_mapping":"24C9","symbol":"\u24E3"},9444:{"value":"24E4","name":"CIRCLED LATIN SMALL LETTER U","category":"So","class":"0","bidirectional_category":"L","mapping":" 0075","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24CA","lowercase_mapping":"","titlecase_mapping":"24CA","symbol":"\u24E4"},9445:{"value":"24E5","name":"CIRCLED LATIN SMALL LETTER V","category":"So","class":"0","bidirectional_category":"L","mapping":" 0076","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24CB","lowercase_mapping":"","titlecase_mapping":"24CB","symbol":"\u24E5"},9446:{"value":"24E6","name":"CIRCLED LATIN SMALL LETTER W","category":"So","class":"0","bidirectional_category":"L","mapping":" 0077","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24CC","lowercase_mapping":"","titlecase_mapping":"24CC","symbol":"\u24E6"},9447:{"value":"24E7","name":"CIRCLED LATIN SMALL LETTER X","category":"So","class":"0","bidirectional_category":"L","mapping":" 0078","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24CD","lowercase_mapping":"","titlecase_mapping":"24CD","symbol":"\u24E7"},9448:{"value":"24E8","name":"CIRCLED LATIN SMALL LETTER Y","category":"So","class":"0","bidirectional_category":"L","mapping":" 0079","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24CE","lowercase_mapping":"","titlecase_mapping":"24CE","symbol":"\u24E8"},9449:{"value":"24E9","name":"CIRCLED LATIN SMALL LETTER Z","category":"So","class":"0","bidirectional_category":"L","mapping":" 007A","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"24CF","lowercase_mapping":"","titlecase_mapping":"24CF","symbol":"\u24E9"},9472:{"value":"2500","name":"BOX DRAWINGS LIGHT HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2500"},9473:{"value":"2501","name":"BOX DRAWINGS HEAVY HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2501"},9474:{"value":"2502","name":"BOX DRAWINGS LIGHT VERTICAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT VERTICAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2502"},9475:{"value":"2503","name":"BOX DRAWINGS HEAVY VERTICAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY VERTICAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2503"},9476:{"value":"2504","name":"BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT TRIPLE DASH HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2504"},9477:{"value":"2505","name":"BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY TRIPLE DASH HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2505"},9478:{"value":"2506","name":"BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT TRIPLE DASH VERTICAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2506"},9479:{"value":"2507","name":"BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY TRIPLE DASH VERTICAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2507"},9480:{"value":"2508","name":"BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT QUADRUPLE DASH HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2508"},9481:{"value":"2509","name":"BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY QUADRUPLE DASH HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2509"},9482:{"value":"250A","name":"BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT QUADRUPLE DASH VERTICAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u250A"},9483:{"value":"250B","name":"BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY QUADRUPLE DASH VERTICAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u250B"},9484:{"value":"250C","name":"BOX DRAWINGS LIGHT DOWN AND RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT DOWN AND RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u250C"},9485:{"value":"250D","name":"BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN LIGHT AND RIGHT HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u250D"},9486:{"value":"250E","name":"BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN HEAVY AND RIGHT LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u250E"},9487:{"value":"250F","name":"BOX DRAWINGS HEAVY DOWN AND RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY DOWN AND RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u250F"},9488:{"value":"2510","name":"BOX DRAWINGS LIGHT DOWN AND LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT DOWN AND LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2510"},9489:{"value":"2511","name":"BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN LIGHT AND LEFT HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2511"},9490:{"value":"2512","name":"BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN HEAVY AND LEFT LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2512"},9491:{"value":"2513","name":"BOX DRAWINGS HEAVY DOWN AND LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY DOWN AND LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2513"},9492:{"value":"2514","name":"BOX DRAWINGS LIGHT UP AND RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT UP AND RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2514"},9493:{"value":"2515","name":"BOX DRAWINGS UP LIGHT AND RIGHT HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP LIGHT AND RIGHT HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2515"},9494:{"value":"2516","name":"BOX DRAWINGS UP HEAVY AND RIGHT LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP HEAVY AND RIGHT LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2516"},9495:{"value":"2517","name":"BOX DRAWINGS HEAVY UP AND RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY UP AND RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2517"},9496:{"value":"2518","name":"BOX DRAWINGS LIGHT UP AND LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT UP AND LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2518"},9497:{"value":"2519","name":"BOX DRAWINGS UP LIGHT AND LEFT HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP LIGHT AND LEFT HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2519"},9498:{"value":"251A","name":"BOX DRAWINGS UP HEAVY AND LEFT LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP HEAVY AND LEFT LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u251A"},9499:{"value":"251B","name":"BOX DRAWINGS HEAVY UP AND LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY UP AND LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u251B"},9500:{"value":"251C","name":"BOX DRAWINGS LIGHT VERTICAL AND RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT VERTICAL AND RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u251C"},9501:{"value":"251D","name":"BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL LIGHT AND RIGHT HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u251D"},9502:{"value":"251E","name":"BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP HEAVY AND RIGHT DOWN LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u251E"},9503:{"value":"251F","name":"BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN HEAVY AND RIGHT UP LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u251F"},9504:{"value":"2520","name":"BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL HEAVY AND RIGHT LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2520"},9505:{"value":"2521","name":"BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN LIGHT AND RIGHT UP HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2521"},9506:{"value":"2522","name":"BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP LIGHT AND RIGHT DOWN HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2522"},9507:{"value":"2523","name":"BOX DRAWINGS HEAVY VERTICAL AND RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY VERTICAL AND RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2523"},9508:{"value":"2524","name":"BOX DRAWINGS LIGHT VERTICAL AND LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT VERTICAL AND LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2524"},9509:{"value":"2525","name":"BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL LIGHT AND LEFT HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2525"},9510:{"value":"2526","name":"BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP HEAVY AND LEFT DOWN LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2526"},9511:{"value":"2527","name":"BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN HEAVY AND LEFT UP LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2527"},9512:{"value":"2528","name":"BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL HEAVY AND LEFT LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2528"},9513:{"value":"2529","name":"BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN LIGHT AND LEFT UP HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2529"},9514:{"value":"252A","name":"BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP LIGHT AND LEFT DOWN HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u252A"},9515:{"value":"252B","name":"BOX DRAWINGS HEAVY VERTICAL AND LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY VERTICAL AND LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u252B"},9516:{"value":"252C","name":"BOX DRAWINGS LIGHT DOWN AND HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT DOWN AND HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u252C"},9517:{"value":"252D","name":"BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LEFT HEAVY AND RIGHT DOWN LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u252D"},9518:{"value":"252E","name":"BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS RIGHT HEAVY AND LEFT DOWN LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u252E"},9519:{"value":"252F","name":"BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN LIGHT AND HORIZONTAL HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u252F"},9520:{"value":"2530","name":"BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN HEAVY AND HORIZONTAL LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2530"},9521:{"value":"2531","name":"BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS RIGHT LIGHT AND LEFT DOWN HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2531"},9522:{"value":"2532","name":"BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LEFT LIGHT AND RIGHT DOWN HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2532"},9523:{"value":"2533","name":"BOX DRAWINGS HEAVY DOWN AND HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY DOWN AND HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2533"},9524:{"value":"2534","name":"BOX DRAWINGS LIGHT UP AND HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT UP AND HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2534"},9525:{"value":"2535","name":"BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LEFT HEAVY AND RIGHT UP LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2535"},9526:{"value":"2536","name":"BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS RIGHT HEAVY AND LEFT UP LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2536"},9527:{"value":"2537","name":"BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP LIGHT AND HORIZONTAL HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2537"},9528:{"value":"2538","name":"BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP HEAVY AND HORIZONTAL LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2538"},9529:{"value":"2539","name":"BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS RIGHT LIGHT AND LEFT UP HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2539"},9530:{"value":"253A","name":"BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LEFT LIGHT AND RIGHT UP HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u253A"},9531:{"value":"253B","name":"BOX DRAWINGS HEAVY UP AND HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY UP AND HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u253B"},9532:{"value":"253C","name":"BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT VERTICAL AND HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u253C"},9533:{"value":"253D","name":"BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LEFT HEAVY AND RIGHT VERTICAL LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u253D"},9534:{"value":"253E","name":"BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS RIGHT HEAVY AND LEFT VERTICAL LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u253E"},9535:{"value":"253F","name":"BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL LIGHT AND HORIZONTAL HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u253F"},9536:{"value":"2540","name":"BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP HEAVY AND DOWN HORIZONTAL LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2540"},9537:{"value":"2541","name":"BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN HEAVY AND UP HORIZONTAL LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2541"},9538:{"value":"2542","name":"BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL HEAVY AND HORIZONTAL LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2542"},9539:{"value":"2543","name":"BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LEFT UP HEAVY AND RIGHT DOWN LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2543"},9540:{"value":"2544","name":"BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS RIGHT UP HEAVY AND LEFT DOWN LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2544"},9541:{"value":"2545","name":"BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LEFT DOWN HEAVY AND RIGHT UP LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2545"},9542:{"value":"2546","name":"BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS RIGHT DOWN HEAVY AND LEFT UP LIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2546"},9543:{"value":"2547","name":"BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN LIGHT AND UP HORIZONTAL HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2547"},9544:{"value":"2548","name":"BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP LIGHT AND DOWN HORIZONTAL HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2548"},9545:{"value":"2549","name":"BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS RIGHT LIGHT AND LEFT VERTICAL HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2549"},9546:{"value":"254A","name":"BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LEFT LIGHT AND RIGHT VERTICAL HEAVY","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u254A"},9547:{"value":"254B","name":"BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY VERTICAL AND HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u254B"},9548:{"value":"254C","name":"BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT DOUBLE DASH HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u254C"},9549:{"value":"254D","name":"BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY DOUBLE DASH HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u254D"},9550:{"value":"254E","name":"BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT DOUBLE DASH VERTICAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u254E"},9551:{"value":"254F","name":"BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY DOUBLE DASH VERTICAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u254F"},9552:{"value":"2550","name":"BOX DRAWINGS DOUBLE HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOUBLE HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2550"},9553:{"value":"2551","name":"BOX DRAWINGS DOUBLE VERTICAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOUBLE VERTICAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2551"},9554:{"value":"2552","name":"BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN SINGLE AND RIGHT DOUBLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2552"},9555:{"value":"2553","name":"BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN DOUBLE AND RIGHT SINGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2553"},9556:{"value":"2554","name":"BOX DRAWINGS DOUBLE DOWN AND RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOUBLE DOWN AND RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2554"},9557:{"value":"2555","name":"BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN SINGLE AND LEFT DOUBLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2555"},9558:{"value":"2556","name":"BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN DOUBLE AND LEFT SINGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2556"},9559:{"value":"2557","name":"BOX DRAWINGS DOUBLE DOWN AND LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOUBLE DOWN AND LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2557"},9560:{"value":"2558","name":"BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP SINGLE AND RIGHT DOUBLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2558"},9561:{"value":"2559","name":"BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP DOUBLE AND RIGHT SINGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2559"},9562:{"value":"255A","name":"BOX DRAWINGS DOUBLE UP AND RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOUBLE UP AND RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u255A"},9563:{"value":"255B","name":"BOX DRAWINGS UP SINGLE AND LEFT DOUBLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP SINGLE AND LEFT DOUBLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u255B"},9564:{"value":"255C","name":"BOX DRAWINGS UP DOUBLE AND LEFT SINGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP DOUBLE AND LEFT SINGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u255C"},9565:{"value":"255D","name":"BOX DRAWINGS DOUBLE UP AND LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOUBLE UP AND LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u255D"},9566:{"value":"255E","name":"BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL SINGLE AND RIGHT DOUBLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u255E"},9567:{"value":"255F","name":"BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL DOUBLE AND RIGHT SINGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u255F"},9568:{"value":"2560","name":"BOX DRAWINGS DOUBLE VERTICAL AND RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOUBLE VERTICAL AND RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2560"},9569:{"value":"2561","name":"BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL SINGLE AND LEFT DOUBLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2561"},9570:{"value":"2562","name":"BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL DOUBLE AND LEFT SINGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2562"},9571:{"value":"2563","name":"BOX DRAWINGS DOUBLE VERTICAL AND LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOUBLE VERTICAL AND LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2563"},9572:{"value":"2564","name":"BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN SINGLE AND HORIZONTAL DOUBLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2564"},9573:{"value":"2565","name":"BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOWN DOUBLE AND HORIZONTAL SINGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2565"},9574:{"value":"2566","name":"BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOUBLE DOWN AND HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2566"},9575:{"value":"2567","name":"BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP SINGLE AND HORIZONTAL DOUBLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2567"},9576:{"value":"2568","name":"BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS UP DOUBLE AND HORIZONTAL SINGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2568"},9577:{"value":"2569","name":"BOX DRAWINGS DOUBLE UP AND HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOUBLE UP AND HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2569"},9578:{"value":"256A","name":"BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL SINGLE AND HORIZONTAL DOUBLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u256A"},9579:{"value":"256B","name":"BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS VERTICAL DOUBLE AND HORIZONTAL SINGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u256B"},9580:{"value":"256C","name":"BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS DOUBLE VERTICAL AND HORIZONTAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u256C"},9581:{"value":"256D","name":"BOX DRAWINGS LIGHT ARC DOWN AND RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT ARC DOWN AND RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u256D"},9582:{"value":"256E","name":"BOX DRAWINGS LIGHT ARC DOWN AND LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT ARC DOWN AND LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u256E"},9583:{"value":"256F","name":"BOX DRAWINGS LIGHT ARC UP AND LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT ARC UP AND LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u256F"},9584:{"value":"2570","name":"BOX DRAWINGS LIGHT ARC UP AND RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT ARC UP AND RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2570"},9585:{"value":"2571","name":"BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2571"},9586:{"value":"2572","name":"BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2572"},9587:{"value":"2573","name":"BOX DRAWINGS LIGHT DIAGONAL CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT DIAGONAL CROSS","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2573"},9588:{"value":"2574","name":"BOX DRAWINGS LIGHT LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2574"},9589:{"value":"2575","name":"BOX DRAWINGS LIGHT UP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT UP","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2575"},9590:{"value":"2576","name":"BOX DRAWINGS LIGHT RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2576"},9591:{"value":"2577","name":"BOX DRAWINGS LIGHT DOWN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT DOWN","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2577"},9592:{"value":"2578","name":"BOX DRAWINGS HEAVY LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY LEFT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2578"},9593:{"value":"2579","name":"BOX DRAWINGS HEAVY UP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY UP","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2579"},9594:{"value":"257A","name":"BOX DRAWINGS HEAVY RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u257A"},9595:{"value":"257B","name":"BOX DRAWINGS HEAVY DOWN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY DOWN","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u257B"},9596:{"value":"257C","name":"BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT LEFT AND HEAVY RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u257C"},9597:{"value":"257D","name":"BOX DRAWINGS LIGHT UP AND HEAVY DOWN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS LIGHT UP AND HEAVY DOWN","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u257D"},9598:{"value":"257E","name":"BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY LEFT AND LIGHT RIGHT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u257E"},9599:{"value":"257F","name":"BOX DRAWINGS HEAVY UP AND LIGHT DOWN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FORMS HEAVY UP AND LIGHT DOWN","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u257F"},9600:{"value":"2580","name":"UPPER HALF BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2580"},9601:{"value":"2581","name":"LOWER ONE EIGHTH BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2581"},9602:{"value":"2582","name":"LOWER ONE QUARTER BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2582"},9603:{"value":"2583","name":"LOWER THREE EIGHTHS BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2583"},9604:{"value":"2584","name":"LOWER HALF BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2584"},9605:{"value":"2585","name":"LOWER FIVE EIGHTHS BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2585"},9606:{"value":"2586","name":"LOWER THREE QUARTERS BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LOWER THREE QUARTER BLOCK","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2586"},9607:{"value":"2587","name":"LOWER SEVEN EIGHTHS BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2587"},9608:{"value":"2588","name":"FULL BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2588"},9609:{"value":"2589","name":"LEFT SEVEN EIGHTHS BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2589"},9610:{"value":"258A","name":"LEFT THREE QUARTERS BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT THREE QUARTER BLOCK","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u258A"},9611:{"value":"258B","name":"LEFT FIVE EIGHTHS BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u258B"},9612:{"value":"258C","name":"LEFT HALF BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u258C"},9613:{"value":"258D","name":"LEFT THREE EIGHTHS BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u258D"},9614:{"value":"258E","name":"LEFT ONE QUARTER BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u258E"},9615:{"value":"258F","name":"LEFT ONE EIGHTH BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u258F"},9616:{"value":"2590","name":"RIGHT HALF BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2590"},9617:{"value":"2591","name":"LIGHT SHADE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2591"},9618:{"value":"2592","name":"MEDIUM SHADE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2592"},9619:{"value":"2593","name":"DARK SHADE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2593"},9620:{"value":"2594","name":"UPPER ONE EIGHTH BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2594"},9621:{"value":"2595","name":"RIGHT ONE EIGHTH BLOCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2595"},9622:{"value":"2596","name":"QUADRANT LOWER LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2596"},9623:{"value":"2597","name":"QUADRANT LOWER RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2597"},9624:{"value":"2598","name":"QUADRANT UPPER LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2598"},9625:{"value":"2599","name":"QUADRANT UPPER LEFT AND LOWER LEFT AND LOWER RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2599"},9626:{"value":"259A","name":"QUADRANT UPPER LEFT AND LOWER RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u259A"},9627:{"value":"259B","name":"QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u259B"},9628:{"value":"259C","name":"QUADRANT UPPER LEFT AND UPPER RIGHT AND LOWER RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u259C"},9629:{"value":"259D","name":"QUADRANT UPPER RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u259D"},9630:{"value":"259E","name":"QUADRANT UPPER RIGHT AND LOWER LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u259E"},9631:{"value":"259F","name":"QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u259F"},9632:{"value":"25A0","name":"BLACK SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25A0"},9633:{"value":"25A1","name":"WHITE SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25A1"},9634:{"value":"25A2","name":"WHITE SQUARE WITH ROUNDED CORNERS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25A2"},9635:{"value":"25A3","name":"WHITE SQUARE CONTAINING BLACK SMALL SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25A3"},9636:{"value":"25A4","name":"SQUARE WITH HORIZONTAL FILL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25A4"},9637:{"value":"25A5","name":"SQUARE WITH VERTICAL FILL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25A5"},9638:{"value":"25A6","name":"SQUARE WITH ORTHOGONAL CROSSHATCH FILL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25A6"},9639:{"value":"25A7","name":"SQUARE WITH UPPER LEFT TO LOWER RIGHT FILL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25A7"},9640:{"value":"25A8","name":"SQUARE WITH UPPER RIGHT TO LOWER LEFT FILL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25A8"},9641:{"value":"25A9","name":"SQUARE WITH DIAGONAL CROSSHATCH FILL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25A9"},9642:{"value":"25AA","name":"BLACK SMALL SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25AA"},9643:{"value":"25AB","name":"WHITE SMALL SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25AB"},9644:{"value":"25AC","name":"BLACK RECTANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25AC"},9645:{"value":"25AD","name":"WHITE RECTANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25AD"},9646:{"value":"25AE","name":"BLACK VERTICAL RECTANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25AE"},9647:{"value":"25AF","name":"WHITE VERTICAL RECTANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25AF"},9648:{"value":"25B0","name":"BLACK PARALLELOGRAM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25B0"},9649:{"value":"25B1","name":"WHITE PARALLELOGRAM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25B1"},9650:{"value":"25B2","name":"BLACK UP-POINTING TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK UP POINTING TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25B2"},9651:{"value":"25B3","name":"WHITE UP-POINTING TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE UP POINTING TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25B3"},9652:{"value":"25B4","name":"BLACK UP-POINTING SMALL TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK UP POINTING SMALL TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25B4"},9653:{"value":"25B5","name":"WHITE UP-POINTING SMALL TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE UP POINTING SMALL TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25B5"},9654:{"value":"25B6","name":"BLACK RIGHT-POINTING TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK RIGHT POINTING TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25B6"},9656:{"value":"25B8","name":"BLACK RIGHT-POINTING SMALL TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK RIGHT POINTING SMALL TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25B8"},9657:{"value":"25B9","name":"WHITE RIGHT-POINTING SMALL TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE RIGHT POINTING SMALL TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25B9"},9658:{"value":"25BA","name":"BLACK RIGHT-POINTING POINTER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK RIGHT POINTING POINTER","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25BA"},9659:{"value":"25BB","name":"WHITE RIGHT-POINTING POINTER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE RIGHT POINTING POINTER","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25BB"},9660:{"value":"25BC","name":"BLACK DOWN-POINTING TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK DOWN POINTING TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25BC"},9661:{"value":"25BD","name":"WHITE DOWN-POINTING TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE DOWN POINTING TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25BD"},9662:{"value":"25BE","name":"BLACK DOWN-POINTING SMALL TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK DOWN POINTING SMALL TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25BE"},9663:{"value":"25BF","name":"WHITE DOWN-POINTING SMALL TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE DOWN POINTING SMALL TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25BF"},9664:{"value":"25C0","name":"BLACK LEFT-POINTING TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK LEFT POINTING TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25C0"},9666:{"value":"25C2","name":"BLACK LEFT-POINTING SMALL TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK LEFT POINTING SMALL TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25C2"},9667:{"value":"25C3","name":"WHITE LEFT-POINTING SMALL TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE LEFT POINTING SMALL TRIANGLE","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25C3"},9668:{"value":"25C4","name":"BLACK LEFT-POINTING POINTER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK LEFT POINTING POINTER","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25C4"},9669:{"value":"25C5","name":"WHITE LEFT-POINTING POINTER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE LEFT POINTING POINTER","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25C5"},9670:{"value":"25C6","name":"BLACK DIAMOND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25C6"},9671:{"value":"25C7","name":"WHITE DIAMOND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25C7"},9672:{"value":"25C8","name":"WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25C8"},9673:{"value":"25C9","name":"FISHEYE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25C9"},9674:{"value":"25CA","name":"LOZENGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25CA"},9675:{"value":"25CB","name":"WHITE CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25CB"},9676:{"value":"25CC","name":"DOTTED CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25CC"},9677:{"value":"25CD","name":"CIRCLE WITH VERTICAL FILL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25CD"},9678:{"value":"25CE","name":"BULLSEYE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25CE"},9679:{"value":"25CF","name":"BLACK CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25CF"},9680:{"value":"25D0","name":"CIRCLE WITH LEFT HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25D0"},9681:{"value":"25D1","name":"CIRCLE WITH RIGHT HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25D1"},9682:{"value":"25D2","name":"CIRCLE WITH LOWER HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25D2"},9683:{"value":"25D3","name":"CIRCLE WITH UPPER HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25D3"},9684:{"value":"25D4","name":"CIRCLE WITH UPPER RIGHT QUADRANT BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25D4"},9685:{"value":"25D5","name":"CIRCLE WITH ALL BUT UPPER LEFT QUADRANT BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25D5"},9686:{"value":"25D6","name":"LEFT HALF BLACK CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25D6"},9687:{"value":"25D7","name":"RIGHT HALF BLACK CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25D7"},9688:{"value":"25D8","name":"INVERSE BULLET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25D8"},9689:{"value":"25D9","name":"INVERSE WHITE CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25D9"},9690:{"value":"25DA","name":"UPPER HALF INVERSE WHITE CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25DA"},9691:{"value":"25DB","name":"LOWER HALF INVERSE WHITE CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25DB"},9692:{"value":"25DC","name":"UPPER LEFT QUADRANT CIRCULAR ARC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25DC"},9693:{"value":"25DD","name":"UPPER RIGHT QUADRANT CIRCULAR ARC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25DD"},9694:{"value":"25DE","name":"LOWER RIGHT QUADRANT CIRCULAR ARC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25DE"},9695:{"value":"25DF","name":"LOWER LEFT QUADRANT CIRCULAR ARC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25DF"},9696:{"value":"25E0","name":"UPPER HALF CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25E0"},9697:{"value":"25E1","name":"LOWER HALF CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25E1"},9698:{"value":"25E2","name":"BLACK LOWER RIGHT TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25E2"},9699:{"value":"25E3","name":"BLACK LOWER LEFT TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25E3"},9700:{"value":"25E4","name":"BLACK UPPER LEFT TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25E4"},9701:{"value":"25E5","name":"BLACK UPPER RIGHT TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25E5"},9702:{"value":"25E6","name":"WHITE BULLET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25E6"},9703:{"value":"25E7","name":"SQUARE WITH LEFT HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25E7"},9704:{"value":"25E8","name":"SQUARE WITH RIGHT HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25E8"},9705:{"value":"25E9","name":"SQUARE WITH UPPER LEFT DIAGONAL HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25E9"},9706:{"value":"25EA","name":"SQUARE WITH LOWER RIGHT DIAGONAL HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25EA"},9707:{"value":"25EB","name":"WHITE SQUARE WITH VERTICAL BISECTING LINE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25EB"},9708:{"value":"25EC","name":"WHITE UP-POINTING TRIANGLE WITH DOT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE UP POINTING TRIANGLE WITH DOT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25EC"},9709:{"value":"25ED","name":"UP-POINTING TRIANGLE WITH LEFT HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP POINTING TRIANGLE WITH LEFT HALF BLACK","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25ED"},9710:{"value":"25EE","name":"UP-POINTING TRIANGLE WITH RIGHT HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"UP POINTING TRIANGLE WITH RIGHT HALF BLACK","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25EE"},9711:{"value":"25EF","name":"LARGE CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25EF"},9712:{"value":"25F0","name":"WHITE SQUARE WITH UPPER LEFT QUADRANT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25F0"},9713:{"value":"25F1","name":"WHITE SQUARE WITH LOWER LEFT QUADRANT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25F1"},9714:{"value":"25F2","name":"WHITE SQUARE WITH LOWER RIGHT QUADRANT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25F2"},9715:{"value":"25F3","name":"WHITE SQUARE WITH UPPER RIGHT QUADRANT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25F3"},9716:{"value":"25F4","name":"WHITE CIRCLE WITH UPPER LEFT QUADRANT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25F4"},9717:{"value":"25F5","name":"WHITE CIRCLE WITH LOWER LEFT QUADRANT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25F5"},9718:{"value":"25F6","name":"WHITE CIRCLE WITH LOWER RIGHT QUADRANT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25F6"},9719:{"value":"25F7","name":"WHITE CIRCLE WITH UPPER RIGHT QUADRANT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u25F7"},9728:{"value":"2600","name":"BLACK SUN WITH RAYS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2600"},9729:{"value":"2601","name":"CLOUD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2601"},9730:{"value":"2602","name":"UMBRELLA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2602"},9731:{"value":"2603","name":"SNOWMAN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2603"},9732:{"value":"2604","name":"COMET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2604"},9733:{"value":"2605","name":"BLACK STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2605"},9734:{"value":"2606","name":"WHITE STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2606"},9735:{"value":"2607","name":"LIGHTNING","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2607"},9736:{"value":"2608","name":"THUNDERSTORM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2608"},9737:{"value":"2609","name":"SUN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2609"},9738:{"value":"260A","name":"ASCENDING NODE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u260A"},9739:{"value":"260B","name":"DESCENDING NODE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u260B"},9740:{"value":"260C","name":"CONJUNCTION","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u260C"},9741:{"value":"260D","name":"OPPOSITION","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u260D"},9742:{"value":"260E","name":"BLACK TELEPHONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u260E"},9743:{"value":"260F","name":"WHITE TELEPHONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u260F"},9744:{"value":"2610","name":"BALLOT BOX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2610"},9745:{"value":"2611","name":"BALLOT BOX WITH CHECK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2611"},9746:{"value":"2612","name":"BALLOT BOX WITH X","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2612"},9747:{"value":"2613","name":"SALTIRE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2613"},9748:{"value":"2614","name":"UMBRELLA WITH RAIN DROPS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2614"},9749:{"value":"2615","name":"HOT BEVERAGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2615"},9750:{"value":"2616","name":"WHITE SHOGI PIECE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2616"},9751:{"value":"2617","name":"BLACK SHOGI PIECE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2617"},9752:{"value":"2618","name":"SHAMROCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2618"},9753:{"value":"2619","name":"REVERSED ROTATED FLORAL HEART BULLET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2619"},9754:{"value":"261A","name":"BLACK LEFT POINTING INDEX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u261A"},9755:{"value":"261B","name":"BLACK RIGHT POINTING INDEX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u261B"},9756:{"value":"261C","name":"WHITE LEFT POINTING INDEX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u261C"},9757:{"value":"261D","name":"WHITE UP POINTING INDEX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u261D"},9758:{"value":"261E","name":"WHITE RIGHT POINTING INDEX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u261E"},9759:{"value":"261F","name":"WHITE DOWN POINTING INDEX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u261F"},9760:{"value":"2620","name":"SKULL AND CROSSBONES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2620"},9761:{"value":"2621","name":"CAUTION SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2621"},9762:{"value":"2622","name":"RADIOACTIVE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2622"},9763:{"value":"2623","name":"BIOHAZARD SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2623"},9764:{"value":"2624","name":"CADUCEUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2624"},9765:{"value":"2625","name":"ANKH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2625"},9766:{"value":"2626","name":"ORTHODOX CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2626"},9767:{"value":"2627","name":"CHI RHO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2627"},9768:{"value":"2628","name":"CROSS OF LORRAINE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2628"},9769:{"value":"2629","name":"CROSS OF JERUSALEM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2629"},9770:{"value":"262A","name":"STAR AND CRESCENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u262A"},9771:{"value":"262B","name":"FARSI SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"SYMBOL OF IRAN","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u262B"},9772:{"value":"262C","name":"ADI SHAKTI","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u262C"},9773:{"value":"262D","name":"HAMMER AND SICKLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u262D"},9774:{"value":"262E","name":"PEACE SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u262E"},9775:{"value":"262F","name":"YIN YANG","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u262F"},9776:{"value":"2630","name":"TRIGRAM FOR HEAVEN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2630"},9777:{"value":"2631","name":"TRIGRAM FOR LAKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2631"},9778:{"value":"2632","name":"TRIGRAM FOR FIRE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2632"},9779:{"value":"2633","name":"TRIGRAM FOR THUNDER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2633"},9780:{"value":"2634","name":"TRIGRAM FOR WIND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2634"},9781:{"value":"2635","name":"TRIGRAM FOR WATER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2635"},9782:{"value":"2636","name":"TRIGRAM FOR MOUNTAIN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2636"},9783:{"value":"2637","name":"TRIGRAM FOR EARTH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2637"},9784:{"value":"2638","name":"WHEEL OF DHARMA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2638"},9785:{"value":"2639","name":"WHITE FROWNING FACE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2639"},9786:{"value":"263A","name":"WHITE SMILING FACE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u263A"},9787:{"value":"263B","name":"BLACK SMILING FACE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u263B"},9788:{"value":"263C","name":"WHITE SUN WITH RAYS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u263C"},9789:{"value":"263D","name":"FIRST QUARTER MOON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u263D"},9790:{"value":"263E","name":"LAST QUARTER MOON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u263E"},9791:{"value":"263F","name":"MERCURY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u263F"},9792:{"value":"2640","name":"FEMALE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2640"},9793:{"value":"2641","name":"EARTH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2641"},9794:{"value":"2642","name":"MALE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2642"},9795:{"value":"2643","name":"JUPITER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2643"},9796:{"value":"2644","name":"SATURN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2644"},9797:{"value":"2645","name":"URANUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2645"},9798:{"value":"2646","name":"NEPTUNE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2646"},9799:{"value":"2647","name":"PLUTO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2647"},9800:{"value":"2648","name":"ARIES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2648"},9801:{"value":"2649","name":"TAURUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2649"},9802:{"value":"264A","name":"GEMINI","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u264A"},9803:{"value":"264B","name":"CANCER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u264B"},9804:{"value":"264C","name":"LEO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u264C"},9805:{"value":"264D","name":"VIRGO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u264D"},9806:{"value":"264E","name":"LIBRA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u264E"},9807:{"value":"264F","name":"SCORPIUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u264F"},9808:{"value":"2650","name":"SAGITTARIUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2650"},9809:{"value":"2651","name":"CAPRICORN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2651"},9810:{"value":"2652","name":"AQUARIUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2652"},9811:{"value":"2653","name":"PISCES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2653"},9812:{"value":"2654","name":"WHITE CHESS KING","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2654"},9813:{"value":"2655","name":"WHITE CHESS QUEEN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2655"},9814:{"value":"2656","name":"WHITE CHESS ROOK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2656"},9815:{"value":"2657","name":"WHITE CHESS BISHOP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2657"},9816:{"value":"2658","name":"WHITE CHESS KNIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2658"},9817:{"value":"2659","name":"WHITE CHESS PAWN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2659"},9818:{"value":"265A","name":"BLACK CHESS KING","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u265A"},9819:{"value":"265B","name":"BLACK CHESS QUEEN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u265B"},9820:{"value":"265C","name":"BLACK CHESS ROOK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u265C"},9821:{"value":"265D","name":"BLACK CHESS BISHOP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u265D"},9822:{"value":"265E","name":"BLACK CHESS KNIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u265E"},9823:{"value":"265F","name":"BLACK CHESS PAWN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u265F"},9824:{"value":"2660","name":"BLACK SPADE SUIT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2660"},9825:{"value":"2661","name":"WHITE HEART SUIT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2661"},9826:{"value":"2662","name":"WHITE DIAMOND SUIT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2662"},9827:{"value":"2663","name":"BLACK CLUB SUIT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2663"},9828:{"value":"2664","name":"WHITE SPADE SUIT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2664"},9829:{"value":"2665","name":"BLACK HEART SUIT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2665"},9830:{"value":"2666","name":"BLACK DIAMOND SUIT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2666"},9831:{"value":"2667","name":"WHITE CLUB SUIT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2667"},9832:{"value":"2668","name":"HOT SPRINGS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2668"},9833:{"value":"2669","name":"QUARTER NOTE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2669"},9834:{"value":"266A","name":"EIGHTH NOTE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u266A"},9835:{"value":"266B","name":"BEAMED EIGHTH NOTES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BARRED EIGHTH NOTES","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u266B"},9836:{"value":"266C","name":"BEAMED SIXTEENTH NOTES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BARRED SIXTEENTH NOTES","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u266C"},9837:{"value":"266D","name":"MUSIC FLAT SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FLAT","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u266D"},9838:{"value":"266E","name":"MUSIC NATURAL SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"NATURAL","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u266E"},9840:{"value":"2670","name":"WEST SYRIAC CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2670"},9841:{"value":"2671","name":"EAST SYRIAC CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2671"},9842:{"value":"2672","name":"UNIVERSAL RECYCLING SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2672"},9843:{"value":"2673","name":"RECYCLING SYMBOL FOR TYPE-1 PLASTICS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2673"},9844:{"value":"2674","name":"RECYCLING SYMBOL FOR TYPE-2 PLASTICS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2674"},9845:{"value":"2675","name":"RECYCLING SYMBOL FOR TYPE-3 PLASTICS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2675"},9846:{"value":"2676","name":"RECYCLING SYMBOL FOR TYPE-4 PLASTICS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2676"},9847:{"value":"2677","name":"RECYCLING SYMBOL FOR TYPE-5 PLASTICS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2677"},9848:{"value":"2678","name":"RECYCLING SYMBOL FOR TYPE-6 PLASTICS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2678"},9849:{"value":"2679","name":"RECYCLING SYMBOL FOR TYPE-7 PLASTICS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2679"},9850:{"value":"267A","name":"RECYCLING SYMBOL FOR GENERIC MATERIALS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u267A"},9851:{"value":"267B","name":"BLACK UNIVERSAL RECYCLING SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u267B"},9852:{"value":"267C","name":"RECYCLED PAPER SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u267C"},9853:{"value":"267D","name":"PARTIALLY-RECYCLED PAPER SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u267D"},9854:{"value":"267E","name":"PERMANENT PAPER SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u267E"},9855:{"value":"267F","name":"WHEELCHAIR SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u267F"},9856:{"value":"2680","name":"DIE FACE-1","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2680"},9857:{"value":"2681","name":"DIE FACE-2","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2681"},9858:{"value":"2682","name":"DIE FACE-3","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2682"},9859:{"value":"2683","name":"DIE FACE-4","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2683"},9860:{"value":"2684","name":"DIE FACE-5","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2684"},9861:{"value":"2685","name":"DIE FACE-6","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2685"},9862:{"value":"2686","name":"WHITE CIRCLE WITH DOT RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2686"},9863:{"value":"2687","name":"WHITE CIRCLE WITH TWO DOTS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2687"},9864:{"value":"2688","name":"BLACK CIRCLE WITH WHITE DOT RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2688"},9865:{"value":"2689","name":"BLACK CIRCLE WITH TWO WHITE DOTS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2689"},9866:{"value":"268A","name":"MONOGRAM FOR YANG","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u268A"},9867:{"value":"268B","name":"MONOGRAM FOR YIN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u268B"},9868:{"value":"268C","name":"DIGRAM FOR GREATER YANG","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u268C"},9869:{"value":"268D","name":"DIGRAM FOR LESSER YIN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u268D"},9870:{"value":"268E","name":"DIGRAM FOR LESSER YANG","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u268E"},9871:{"value":"268F","name":"DIGRAM FOR GREATER YIN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u268F"},9872:{"value":"2690","name":"WHITE FLAG","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2690"},9873:{"value":"2691","name":"BLACK FLAG","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2691"},9874:{"value":"2692","name":"HAMMER AND PICK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2692"},9875:{"value":"2693","name":"ANCHOR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2693"},9876:{"value":"2694","name":"CROSSED SWORDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2694"},9877:{"value":"2695","name":"STAFF OF AESCULAPIUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2695"},9878:{"value":"2696","name":"SCALES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2696"},9879:{"value":"2697","name":"ALEMBIC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2697"},9880:{"value":"2698","name":"FLOWER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2698"},9881:{"value":"2699","name":"GEAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2699"},9882:{"value":"269A","name":"STAFF OF HERMES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u269A"},9883:{"value":"269B","name":"ATOM SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u269B"},9884:{"value":"269C","name":"FLEUR-DE-LIS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u269C"},9885:{"value":"269D","name":"OUTLINED WHITE STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u269D"},9886:{"value":"269E","name":"THREE LINES CONVERGING RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u269E"},9887:{"value":"269F","name":"THREE LINES CONVERGING LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u269F"},9888:{"value":"26A0","name":"WARNING SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26A0"},9889:{"value":"26A1","name":"HIGH VOLTAGE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26A1"},9890:{"value":"26A2","name":"DOUBLED FEMALE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26A2"},9891:{"value":"26A3","name":"DOUBLED MALE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26A3"},9892:{"value":"26A4","name":"INTERLOCKED FEMALE AND MALE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26A4"},9893:{"value":"26A5","name":"MALE AND FEMALE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26A5"},9894:{"value":"26A6","name":"MALE WITH STROKE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26A6"},9895:{"value":"26A7","name":"MALE WITH STROKE AND MALE AND FEMALE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26A7"},9896:{"value":"26A8","name":"VERTICAL MALE WITH STROKE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26A8"},9897:{"value":"26A9","name":"HORIZONTAL MALE WITH STROKE SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26A9"},9898:{"value":"26AA","name":"MEDIUM WHITE CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26AA"},9899:{"value":"26AB","name":"MEDIUM BLACK CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26AB"},9900:{"value":"26AC","name":"MEDIUM SMALL WHITE CIRCLE","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26AC"},9901:{"value":"26AD","name":"MARRIAGE SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26AD"},9902:{"value":"26AE","name":"DIVORCE SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26AE"},9903:{"value":"26AF","name":"UNMARRIED PARTNERSHIP SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26AF"},9904:{"value":"26B0","name":"COFFIN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26B0"},9905:{"value":"26B1","name":"FUNERAL URN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26B1"},9906:{"value":"26B2","name":"NEUTER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26B2"},9907:{"value":"26B3","name":"CERES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26B3"},9908:{"value":"26B4","name":"PALLAS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26B4"},9909:{"value":"26B5","name":"JUNO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26B5"},9910:{"value":"26B6","name":"VESTA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26B6"},9911:{"value":"26B7","name":"CHIRON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26B7"},9912:{"value":"26B8","name":"BLACK MOON LILITH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26B8"},9913:{"value":"26B9","name":"SEXTILE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26B9"},9914:{"value":"26BA","name":"SEMISEXTILE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26BA"},9915:{"value":"26BB","name":"QUINCUNX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26BB"},9916:{"value":"26BC","name":"SESQUIQUADRATE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26BC"},9917:{"value":"26BD","name":"SOCCER BALL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26BD"},9918:{"value":"26BE","name":"BASEBALL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26BE"},9919:{"value":"26BF","name":"SQUARED KEY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26BF"},9920:{"value":"26C0","name":"WHITE DRAUGHTS MAN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26C0"},9921:{"value":"26C1","name":"WHITE DRAUGHTS KING","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26C1"},9922:{"value":"26C2","name":"BLACK DRAUGHTS MAN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26C2"},9923:{"value":"26C3","name":"BLACK DRAUGHTS KING","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26C3"},9924:{"value":"26C4","name":"SNOWMAN WITHOUT SNOW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26C4"},9925:{"value":"26C5","name":"SUN BEHIND CLOUD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26C5"},9926:{"value":"26C6","name":"RAIN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26C6"},9927:{"value":"26C7","name":"BLACK SNOWMAN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26C7"},9928:{"value":"26C8","name":"THUNDER CLOUD AND RAIN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26C8"},9929:{"value":"26C9","name":"TURNED WHITE SHOGI PIECE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26C9"},9930:{"value":"26CA","name":"TURNED BLACK SHOGI PIECE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26CA"},9931:{"value":"26CB","name":"WHITE DIAMOND IN SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26CB"},9932:{"value":"26CC","name":"CROSSING LANES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26CC"},9933:{"value":"26CD","name":"DISABLED CAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26CD"},9934:{"value":"26CE","name":"OPHIUCHUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26CE"},9935:{"value":"26CF","name":"PICK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26CF"},9936:{"value":"26D0","name":"CAR SLIDING","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26D0"},9937:{"value":"26D1","name":"HELMET WITH WHITE CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26D1"},9938:{"value":"26D2","name":"CIRCLED CROSSING LANES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26D2"},9939:{"value":"26D3","name":"CHAINS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26D3"},9940:{"value":"26D4","name":"NO ENTRY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26D4"},9941:{"value":"26D5","name":"ALTERNATE ONE-WAY LEFT WAY TRAFFIC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26D5"},9942:{"value":"26D6","name":"BLACK TWO-WAY LEFT WAY TRAFFIC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26D6"},9943:{"value":"26D7","name":"WHITE TWO-WAY LEFT WAY TRAFFIC","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26D7"},9944:{"value":"26D8","name":"BLACK LEFT LANE MERGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26D8"},9945:{"value":"26D9","name":"WHITE LEFT LANE MERGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26D9"},9946:{"value":"26DA","name":"DRIVE SLOW SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26DA"},9947:{"value":"26DB","name":"HEAVY WHITE DOWN-POINTING TRIANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26DB"},9948:{"value":"26DC","name":"LEFT CLOSED ENTRY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26DC"},9949:{"value":"26DD","name":"SQUARED SALTIRE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26DD"},9950:{"value":"26DE","name":"FALLING DIAGONAL IN WHITE CIRCLE IN BLACK SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26DE"},9951:{"value":"26DF","name":"BLACK TRUCK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26DF"},9952:{"value":"26E0","name":"RESTRICTED LEFT ENTRY-1","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26E0"},9953:{"value":"26E1","name":"RESTRICTED LEFT ENTRY-2","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26E1"},9954:{"value":"26E2","name":"ASTRONOMICAL SYMBOL FOR URANUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26E2"},9955:{"value":"26E3","name":"HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26E3"},9956:{"value":"26E4","name":"PENTAGRAM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26E4"},9957:{"value":"26E5","name":"RIGHT-HANDED INTERLACED PENTAGRAM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26E5"},9958:{"value":"26E6","name":"LEFT-HANDED INTERLACED PENTAGRAM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26E6"},9959:{"value":"26E7","name":"INVERTED PENTAGRAM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26E7"},9960:{"value":"26E8","name":"BLACK CROSS ON SHIELD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26E8"},9961:{"value":"26E9","name":"SHINTO SHRINE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26E9"},9962:{"value":"26EA","name":"CHURCH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26EA"},9963:{"value":"26EB","name":"CASTLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26EB"},9964:{"value":"26EC","name":"HISTORIC SITE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26EC"},9965:{"value":"26ED","name":"GEAR WITHOUT HUB","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26ED"},9966:{"value":"26EE","name":"GEAR WITH HANDLES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26EE"},9967:{"value":"26EF","name":"MAP SYMBOL FOR LIGHTHOUSE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26EF"},9968:{"value":"26F0","name":"MOUNTAIN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26F0"},9969:{"value":"26F1","name":"UMBRELLA ON GROUND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26F1"},9970:{"value":"26F2","name":"FOUNTAIN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26F2"},9971:{"value":"26F3","name":"FLAG IN HOLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26F3"},9972:{"value":"26F4","name":"FERRY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26F4"},9973:{"value":"26F5","name":"SAILBOAT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26F5"},9974:{"value":"26F6","name":"SQUARE FOUR CORNERS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26F6"},9975:{"value":"26F7","name":"SKIER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26F7"},9976:{"value":"26F8","name":"ICE SKATE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26F8"},9977:{"value":"26F9","name":"PERSON WITH BALL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26F9"},9978:{"value":"26FA","name":"TENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26FA"},9979:{"value":"26FB","name":"JAPANESE BANK SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26FB"},9980:{"value":"26FC","name":"HEADSTONE GRAVEYARD SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26FC"},9981:{"value":"26FD","name":"FUEL PUMP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26FD"},9982:{"value":"26FE","name":"CUP ON BLACK SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26FE"},9983:{"value":"26FF","name":"WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u26FF"},9984:{"value":"2700","name":"BLACK SAFETY SCISSORS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2700"},9985:{"value":"2701","name":"UPPER BLADE SCISSORS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2701"},9986:{"value":"2702","name":"BLACK SCISSORS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2702"},9987:{"value":"2703","name":"LOWER BLADE SCISSORS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2703"},9988:{"value":"2704","name":"WHITE SCISSORS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2704"},9989:{"value":"2705","name":"WHITE HEAVY CHECK MARK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2705"},9990:{"value":"2706","name":"TELEPHONE LOCATION SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2706"},9991:{"value":"2707","name":"TAPE DRIVE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2707"},9992:{"value":"2708","name":"AIRPLANE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2708"},9993:{"value":"2709","name":"ENVELOPE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2709"},9994:{"value":"270A","name":"RAISED FIST","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u270A"},9995:{"value":"270B","name":"RAISED HAND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u270B"},9996:{"value":"270C","name":"VICTORY HAND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u270C"},9997:{"value":"270D","name":"WRITING HAND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u270D"},9998:{"value":"270E","name":"LOWER RIGHT PENCIL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u270E"},9999:{"value":"270F","name":"PENCIL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u270F"},10000:{"value":"2710","name":"UPPER RIGHT PENCIL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2710"},10001:{"value":"2711","name":"WHITE NIB","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2711"},10002:{"value":"2712","name":"BLACK NIB","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2712"},10003:{"value":"2713","name":"CHECK MARK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2713"},10004:{"value":"2714","name":"HEAVY CHECK MARK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2714"},10005:{"value":"2715","name":"MULTIPLICATION X","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2715"},10006:{"value":"2716","name":"HEAVY MULTIPLICATION X","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2716"},10007:{"value":"2717","name":"BALLOT X","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2717"},10008:{"value":"2718","name":"HEAVY BALLOT X","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2718"},10009:{"value":"2719","name":"OUTLINED GREEK CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2719"},10010:{"value":"271A","name":"HEAVY GREEK CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u271A"},10011:{"value":"271B","name":"OPEN CENTRE CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"OPEN CENTER CROSS","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u271B"},10012:{"value":"271C","name":"HEAVY OPEN CENTRE CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY OPEN CENTER CROSS","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u271C"},10013:{"value":"271D","name":"LATIN CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u271D"},10014:{"value":"271E","name":"SHADOWED WHITE LATIN CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u271E"},10015:{"value":"271F","name":"OUTLINED LATIN CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u271F"},10016:{"value":"2720","name":"MALTESE CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2720"},10017:{"value":"2721","name":"STAR OF DAVID","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2721"},10018:{"value":"2722","name":"FOUR TEARDROP-SPOKED ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2722"},10019:{"value":"2723","name":"FOUR BALLOON-SPOKED ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2723"},10020:{"value":"2724","name":"HEAVY FOUR BALLOON-SPOKED ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2724"},10021:{"value":"2725","name":"FOUR CLUB-SPOKED ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2725"},10022:{"value":"2726","name":"BLACK FOUR POINTED STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2726"},10023:{"value":"2727","name":"WHITE FOUR POINTED STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2727"},10024:{"value":"2728","name":"SPARKLES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2728"},10025:{"value":"2729","name":"STRESS OUTLINED WHITE STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2729"},10026:{"value":"272A","name":"CIRCLED WHITE STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u272A"},10027:{"value":"272B","name":"OPEN CENTRE BLACK STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"OPEN CENTER BLACK STAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u272B"},10028:{"value":"272C","name":"BLACK CENTRE WHITE STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK CENTER WHITE STAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u272C"},10029:{"value":"272D","name":"OUTLINED BLACK STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u272D"},10030:{"value":"272E","name":"HEAVY OUTLINED BLACK STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u272E"},10031:{"value":"272F","name":"PINWHEEL STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u272F"},10032:{"value":"2730","name":"SHADOWED WHITE STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2730"},10033:{"value":"2731","name":"HEAVY ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2731"},10034:{"value":"2732","name":"OPEN CENTRE ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"OPEN CENTER ASTERISK","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2732"},10035:{"value":"2733","name":"EIGHT SPOKED ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2733"},10036:{"value":"2734","name":"EIGHT POINTED BLACK STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2734"},10037:{"value":"2735","name":"EIGHT POINTED PINWHEEL STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2735"},10038:{"value":"2736","name":"SIX POINTED BLACK STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2736"},10039:{"value":"2737","name":"EIGHT POINTED RECTILINEAR BLACK STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2737"},10040:{"value":"2738","name":"HEAVY EIGHT POINTED RECTILINEAR BLACK STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2738"},10041:{"value":"2739","name":"TWELVE POINTED BLACK STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2739"},10042:{"value":"273A","name":"SIXTEEN POINTED ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u273A"},10043:{"value":"273B","name":"TEARDROP-SPOKED ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u273B"},10044:{"value":"273C","name":"OPEN CENTRE TEARDROP-SPOKED ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"OPEN CENTER TEARDROP-SPOKED ASTERISK","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u273C"},10045:{"value":"273D","name":"HEAVY TEARDROP-SPOKED ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u273D"},10046:{"value":"273E","name":"SIX PETALLED BLACK AND WHITE FLORETTE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u273E"},10047:{"value":"273F","name":"BLACK FLORETTE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u273F"},10048:{"value":"2740","name":"WHITE FLORETTE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2740"},10049:{"value":"2741","name":"EIGHT PETALLED OUTLINED BLACK FLORETTE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2741"},10050:{"value":"2742","name":"CIRCLED OPEN CENTRE EIGHT POINTED STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"CIRCLED OPEN CENTER EIGHT POINTED STAR","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2742"},10051:{"value":"2743","name":"HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2743"},10052:{"value":"2744","name":"SNOWFLAKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2744"},10053:{"value":"2745","name":"TIGHT TRIFOLIATE SNOWFLAKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2745"},10054:{"value":"2746","name":"HEAVY CHEVRON SNOWFLAKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2746"},10055:{"value":"2747","name":"SPARKLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2747"},10056:{"value":"2748","name":"HEAVY SPARKLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2748"},10057:{"value":"2749","name":"BALLOON-SPOKED ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2749"},10058:{"value":"274A","name":"EIGHT TEARDROP-SPOKED PROPELLER ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u274A"},10059:{"value":"274B","name":"HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u274B"},10060:{"value":"274C","name":"CROSS MARK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u274C"},10061:{"value":"274D","name":"SHADOWED WHITE CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u274D"},10062:{"value":"274E","name":"NEGATIVE SQUARED CROSS MARK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u274E"},10063:{"value":"274F","name":"LOWER RIGHT DROP-SHADOWED WHITE SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u274F"},10064:{"value":"2750","name":"UPPER RIGHT DROP-SHADOWED WHITE SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2750"},10065:{"value":"2751","name":"LOWER RIGHT SHADOWED WHITE SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2751"},10066:{"value":"2752","name":"UPPER RIGHT SHADOWED WHITE SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2752"},10067:{"value":"2753","name":"BLACK QUESTION MARK ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2753"},10068:{"value":"2754","name":"WHITE QUESTION MARK ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2754"},10069:{"value":"2755","name":"WHITE EXCLAMATION MARK ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2755"},10070:{"value":"2756","name":"BLACK DIAMOND MINUS WHITE X","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2756"},10071:{"value":"2757","name":"HEAVY EXCLAMATION MARK SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2757"},10072:{"value":"2758","name":"LIGHT VERTICAL BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2758"},10073:{"value":"2759","name":"MEDIUM VERTICAL BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2759"},10074:{"value":"275A","name":"HEAVY VERTICAL BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u275A"},10075:{"value":"275B","name":"HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u275B"},10076:{"value":"275C","name":"HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u275C"},10077:{"value":"275D","name":"HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u275D"},10078:{"value":"275E","name":"HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u275E"},10079:{"value":"275F","name":"HEAVY LOW SINGLE COMMA QUOTATION MARK ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u275F"},10080:{"value":"2760","name":"HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2760"},10081:{"value":"2761","name":"CURVED STEM PARAGRAPH SIGN ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2761"},10082:{"value":"2762","name":"HEAVY EXCLAMATION MARK ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2762"},10083:{"value":"2763","name":"HEAVY HEART EXCLAMATION MARK ORNAMENT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2763"},10084:{"value":"2764","name":"HEAVY BLACK HEART","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2764"},10085:{"value":"2765","name":"ROTATED HEAVY BLACK HEART BULLET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2765"},10086:{"value":"2766","name":"FLORAL HEART","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2766"},10087:{"value":"2767","name":"ROTATED FLORAL HEART BULLET","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2767"},10132:{"value":"2794","name":"HEAVY WIDE-HEADED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY WIDE-HEADED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2794"},10133:{"value":"2795","name":"HEAVY PLUS SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2795"},10134:{"value":"2796","name":"HEAVY MINUS SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2796"},10135:{"value":"2797","name":"HEAVY DIVISION SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2797"},10136:{"value":"2798","name":"HEAVY SOUTH EAST ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY LOWER RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2798"},10137:{"value":"2799","name":"HEAVY RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2799"},10138:{"value":"279A","name":"HEAVY NORTH EAST ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY UPPER RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u279A"},10139:{"value":"279B","name":"DRAFTING POINT RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DRAFTING POINT RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u279B"},10140:{"value":"279C","name":"HEAVY ROUND-TIPPED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY ROUND-TIPPED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u279C"},10141:{"value":"279D","name":"TRIANGLE-HEADED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"TRIANGLE-HEADED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u279D"},10142:{"value":"279E","name":"HEAVY TRIANGLE-HEADED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY TRIANGLE-HEADED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u279E"},10143:{"value":"279F","name":"DASHED TRIANGLE-HEADED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"DASHED TRIANGLE-HEADED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u279F"},10144:{"value":"27A0","name":"HEAVY DASHED TRIANGLE-HEADED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY DASHED TRIANGLE-HEADED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27A0"},10145:{"value":"27A1","name":"BLACK RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27A1"},10146:{"value":"27A2","name":"THREE-D TOP-LIGHTED RIGHTWARDS ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"THREE-D TOP-LIGHTED RIGHT ARROWHEAD","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27A2"},10147:{"value":"27A3","name":"THREE-D BOTTOM-LIGHTED RIGHTWARDS ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"THREE-D BOTTOM-LIGHTED RIGHT ARROWHEAD","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27A3"},10148:{"value":"27A4","name":"BLACK RIGHTWARDS ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK RIGHT ARROWHEAD","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27A4"},10149:{"value":"27A5","name":"HEAVY BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY BLACK CURVED DOWN AND RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27A5"},10150:{"value":"27A6","name":"HEAVY BLACK CURVED UPWARDS AND RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY BLACK CURVED UP AND RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27A6"},10151:{"value":"27A7","name":"SQUAT BLACK RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"SQUAT BLACK RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27A7"},10152:{"value":"27A8","name":"HEAVY CONCAVE-POINTED BLACK RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY CONCAVE-POINTED BLACK RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27A8"},10153:{"value":"27A9","name":"RIGHT-SHADED WHITE RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"RIGHT-SHADED WHITE RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27A9"},10154:{"value":"27AA","name":"LEFT-SHADED WHITE RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"LEFT-SHADED WHITE RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27AA"},10155:{"value":"27AB","name":"BACK-TILTED SHADOWED WHITE RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BACK-TILTED SHADOWED WHITE RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27AB"},10156:{"value":"27AC","name":"FRONT-TILTED SHADOWED WHITE RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"FRONT-TILTED SHADOWED WHITE RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27AC"},10157:{"value":"27AD","name":"HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY LOWER RIGHT-SHADOWED WHITE RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27AD"},10158:{"value":"27AE","name":"HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY UPPER RIGHT-SHADOWED WHITE RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27AE"},10159:{"value":"27AF","name":"NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27AF"},10160:{"value":"27B0","name":"CURLY LOOP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27B0"},10161:{"value":"27B1","name":"NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27B1"},10162:{"value":"27B2","name":"CIRCLED HEAVY WHITE RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"CIRCLED HEAVY WHITE RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27B2"},10163:{"value":"27B3","name":"WHITE-FEATHERED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WHITE-FEATHERED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27B3"},10164:{"value":"27B4","name":"BLACK-FEATHERED SOUTH EAST ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK-FEATHERED LOWER RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27B4"},10165:{"value":"27B5","name":"BLACK-FEATHERED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK-FEATHERED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27B5"},10166:{"value":"27B6","name":"BLACK-FEATHERED NORTH EAST ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"BLACK-FEATHERED UPPER RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27B6"},10167:{"value":"27B7","name":"HEAVY BLACK-FEATHERED SOUTH EAST ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY BLACK-FEATHERED LOWER RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27B7"},10168:{"value":"27B8","name":"HEAVY BLACK-FEATHERED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY BLACK-FEATHERED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27B8"},10169:{"value":"27B9","name":"HEAVY BLACK-FEATHERED NORTH EAST ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY BLACK-FEATHERED UPPER RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27B9"},10170:{"value":"27BA","name":"TEARDROP-BARBED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"TEARDROP-BARBED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27BA"},10171:{"value":"27BB","name":"HEAVY TEARDROP-SHANKED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY TEARDROP-SHANKED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27BB"},10172:{"value":"27BC","name":"WEDGE-TAILED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"WEDGE-TAILED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27BC"},10173:{"value":"27BD","name":"HEAVY WEDGE-TAILED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"HEAVY WEDGE-TAILED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27BD"},10174:{"value":"27BE","name":"OPEN-OUTLINED RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"OPEN-OUTLINED RIGHT ARROW","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27BE"},10175:{"value":"27BF","name":"DOUBLE CURLY LOOP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u27BF"},10240:{"value":"2800","name":"BRAILLE PATTERN BLANK","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2800"},10241:{"value":"2801","name":"BRAILLE PATTERN DOTS-1","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2801"},10242:{"value":"2802","name":"BRAILLE PATTERN DOTS-2","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2802"},10243:{"value":"2803","name":"BRAILLE PATTERN DOTS-12","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2803"},10244:{"value":"2804","name":"BRAILLE PATTERN DOTS-3","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2804"},10245:{"value":"2805","name":"BRAILLE PATTERN DOTS-13","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2805"},10246:{"value":"2806","name":"BRAILLE PATTERN DOTS-23","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2806"},10247:{"value":"2807","name":"BRAILLE PATTERN DOTS-123","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2807"},10248:{"value":"2808","name":"BRAILLE PATTERN DOTS-4","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2808"},10249:{"value":"2809","name":"BRAILLE PATTERN DOTS-14","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2809"},10250:{"value":"280A","name":"BRAILLE PATTERN DOTS-24","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u280A"},10251:{"value":"280B","name":"BRAILLE PATTERN DOTS-124","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u280B"},10252:{"value":"280C","name":"BRAILLE PATTERN DOTS-34","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u280C"},10253:{"value":"280D","name":"BRAILLE PATTERN DOTS-134","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u280D"},10254:{"value":"280E","name":"BRAILLE PATTERN DOTS-234","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u280E"},10255:{"value":"280F","name":"BRAILLE PATTERN DOTS-1234","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u280F"},10256:{"value":"2810","name":"BRAILLE PATTERN DOTS-5","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2810"},10257:{"value":"2811","name":"BRAILLE PATTERN DOTS-15","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2811"},10258:{"value":"2812","name":"BRAILLE PATTERN DOTS-25","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2812"},10259:{"value":"2813","name":"BRAILLE PATTERN DOTS-125","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2813"},10260:{"value":"2814","name":"BRAILLE PATTERN DOTS-35","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2814"},10261:{"value":"2815","name":"BRAILLE PATTERN DOTS-135","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2815"},10262:{"value":"2816","name":"BRAILLE PATTERN DOTS-235","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2816"},10263:{"value":"2817","name":"BRAILLE PATTERN DOTS-1235","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2817"},10264:{"value":"2818","name":"BRAILLE PATTERN DOTS-45","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2818"},10265:{"value":"2819","name":"BRAILLE PATTERN DOTS-145","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2819"},10266:{"value":"281A","name":"BRAILLE PATTERN DOTS-245","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u281A"},10267:{"value":"281B","name":"BRAILLE PATTERN DOTS-1245","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u281B"},10268:{"value":"281C","name":"BRAILLE PATTERN DOTS-345","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u281C"},10269:{"value":"281D","name":"BRAILLE PATTERN DOTS-1345","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u281D"},10270:{"value":"281E","name":"BRAILLE PATTERN DOTS-2345","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u281E"},10271:{"value":"281F","name":"BRAILLE PATTERN DOTS-12345","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u281F"},10272:{"value":"2820","name":"BRAILLE PATTERN DOTS-6","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2820"},10273:{"value":"2821","name":"BRAILLE PATTERN DOTS-16","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2821"},10274:{"value":"2822","name":"BRAILLE PATTERN DOTS-26","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2822"},10275:{"value":"2823","name":"BRAILLE PATTERN DOTS-126","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2823"},10276:{"value":"2824","name":"BRAILLE PATTERN DOTS-36","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2824"},10277:{"value":"2825","name":"BRAILLE PATTERN DOTS-136","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2825"},10278:{"value":"2826","name":"BRAILLE PATTERN DOTS-236","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2826"},10279:{"value":"2827","name":"BRAILLE PATTERN DOTS-1236","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2827"},10280:{"value":"2828","name":"BRAILLE PATTERN DOTS-46","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2828"},10281:{"value":"2829","name":"BRAILLE PATTERN DOTS-146","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2829"},10282:{"value":"282A","name":"BRAILLE PATTERN DOTS-246","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u282A"},10283:{"value":"282B","name":"BRAILLE PATTERN DOTS-1246","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u282B"},10284:{"value":"282C","name":"BRAILLE PATTERN DOTS-346","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u282C"},10285:{"value":"282D","name":"BRAILLE PATTERN DOTS-1346","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u282D"},10286:{"value":"282E","name":"BRAILLE PATTERN DOTS-2346","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u282E"},10287:{"value":"282F","name":"BRAILLE PATTERN DOTS-12346","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u282F"},10288:{"value":"2830","name":"BRAILLE PATTERN DOTS-56","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2830"},10289:{"value":"2831","name":"BRAILLE PATTERN DOTS-156","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2831"},10290:{"value":"2832","name":"BRAILLE PATTERN DOTS-256","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2832"},10291:{"value":"2833","name":"BRAILLE PATTERN DOTS-1256","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2833"},10292:{"value":"2834","name":"BRAILLE PATTERN DOTS-356","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2834"},10293:{"value":"2835","name":"BRAILLE PATTERN DOTS-1356","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2835"},10294:{"value":"2836","name":"BRAILLE PATTERN DOTS-2356","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2836"},10295:{"value":"2837","name":"BRAILLE PATTERN DOTS-12356","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2837"},10296:{"value":"2838","name":"BRAILLE PATTERN DOTS-456","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2838"},10297:{"value":"2839","name":"BRAILLE PATTERN DOTS-1456","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2839"},10298:{"value":"283A","name":"BRAILLE PATTERN DOTS-2456","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u283A"},10299:{"value":"283B","name":"BRAILLE PATTERN DOTS-12456","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u283B"},10300:{"value":"283C","name":"BRAILLE PATTERN DOTS-3456","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u283C"},10301:{"value":"283D","name":"BRAILLE PATTERN DOTS-13456","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u283D"},10302:{"value":"283E","name":"BRAILLE PATTERN DOTS-23456","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u283E"},10303:{"value":"283F","name":"BRAILLE PATTERN DOTS-123456","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u283F"},10304:{"value":"2840","name":"BRAILLE PATTERN DOTS-7","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2840"},10305:{"value":"2841","name":"BRAILLE PATTERN DOTS-17","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2841"},10306:{"value":"2842","name":"BRAILLE PATTERN DOTS-27","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2842"},10307:{"value":"2843","name":"BRAILLE PATTERN DOTS-127","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2843"},10308:{"value":"2844","name":"BRAILLE PATTERN DOTS-37","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2844"},10309:{"value":"2845","name":"BRAILLE PATTERN DOTS-137","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2845"},10310:{"value":"2846","name":"BRAILLE PATTERN DOTS-237","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2846"},10311:{"value":"2847","name":"BRAILLE PATTERN DOTS-1237","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2847"},10312:{"value":"2848","name":"BRAILLE PATTERN DOTS-47","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2848"},10313:{"value":"2849","name":"BRAILLE PATTERN DOTS-147","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2849"},10314:{"value":"284A","name":"BRAILLE PATTERN DOTS-247","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u284A"},10315:{"value":"284B","name":"BRAILLE PATTERN DOTS-1247","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u284B"},10316:{"value":"284C","name":"BRAILLE PATTERN DOTS-347","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u284C"},10317:{"value":"284D","name":"BRAILLE PATTERN DOTS-1347","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u284D"},10318:{"value":"284E","name":"BRAILLE PATTERN DOTS-2347","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u284E"},10319:{"value":"284F","name":"BRAILLE PATTERN DOTS-12347","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u284F"},10320:{"value":"2850","name":"BRAILLE PATTERN DOTS-57","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2850"},10321:{"value":"2851","name":"BRAILLE PATTERN DOTS-157","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2851"},10322:{"value":"2852","name":"BRAILLE PATTERN DOTS-257","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2852"},10323:{"value":"2853","name":"BRAILLE PATTERN DOTS-1257","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2853"},10324:{"value":"2854","name":"BRAILLE PATTERN DOTS-357","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2854"},10325:{"value":"2855","name":"BRAILLE PATTERN DOTS-1357","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2855"},10326:{"value":"2856","name":"BRAILLE PATTERN DOTS-2357","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2856"},10327:{"value":"2857","name":"BRAILLE PATTERN DOTS-12357","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2857"},10328:{"value":"2858","name":"BRAILLE PATTERN DOTS-457","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2858"},10329:{"value":"2859","name":"BRAILLE PATTERN DOTS-1457","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2859"},10330:{"value":"285A","name":"BRAILLE PATTERN DOTS-2457","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u285A"},10331:{"value":"285B","name":"BRAILLE PATTERN DOTS-12457","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u285B"},10332:{"value":"285C","name":"BRAILLE PATTERN DOTS-3457","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u285C"},10333:{"value":"285D","name":"BRAILLE PATTERN DOTS-13457","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u285D"},10334:{"value":"285E","name":"BRAILLE PATTERN DOTS-23457","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u285E"},10335:{"value":"285F","name":"BRAILLE PATTERN DOTS-123457","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u285F"},10336:{"value":"2860","name":"BRAILLE PATTERN DOTS-67","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2860"},10337:{"value":"2861","name":"BRAILLE PATTERN DOTS-167","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2861"},10338:{"value":"2862","name":"BRAILLE PATTERN DOTS-267","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2862"},10339:{"value":"2863","name":"BRAILLE PATTERN DOTS-1267","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2863"},10340:{"value":"2864","name":"BRAILLE PATTERN DOTS-367","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2864"},10341:{"value":"2865","name":"BRAILLE PATTERN DOTS-1367","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2865"},10342:{"value":"2866","name":"BRAILLE PATTERN DOTS-2367","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2866"},10343:{"value":"2867","name":"BRAILLE PATTERN DOTS-12367","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2867"},10344:{"value":"2868","name":"BRAILLE PATTERN DOTS-467","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2868"},10345:{"value":"2869","name":"BRAILLE PATTERN DOTS-1467","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2869"},10346:{"value":"286A","name":"BRAILLE PATTERN DOTS-2467","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u286A"},10347:{"value":"286B","name":"BRAILLE PATTERN DOTS-12467","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u286B"},10348:{"value":"286C","name":"BRAILLE PATTERN DOTS-3467","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u286C"},10349:{"value":"286D","name":"BRAILLE PATTERN DOTS-13467","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u286D"},10350:{"value":"286E","name":"BRAILLE PATTERN DOTS-23467","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u286E"},10351:{"value":"286F","name":"BRAILLE PATTERN DOTS-123467","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u286F"},10352:{"value":"2870","name":"BRAILLE PATTERN DOTS-567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2870"},10353:{"value":"2871","name":"BRAILLE PATTERN DOTS-1567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2871"},10354:{"value":"2872","name":"BRAILLE PATTERN DOTS-2567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2872"},10355:{"value":"2873","name":"BRAILLE PATTERN DOTS-12567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2873"},10356:{"value":"2874","name":"BRAILLE PATTERN DOTS-3567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2874"},10357:{"value":"2875","name":"BRAILLE PATTERN DOTS-13567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2875"},10358:{"value":"2876","name":"BRAILLE PATTERN DOTS-23567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2876"},10359:{"value":"2877","name":"BRAILLE PATTERN DOTS-123567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2877"},10360:{"value":"2878","name":"BRAILLE PATTERN DOTS-4567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2878"},10361:{"value":"2879","name":"BRAILLE PATTERN DOTS-14567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2879"},10362:{"value":"287A","name":"BRAILLE PATTERN DOTS-24567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u287A"},10363:{"value":"287B","name":"BRAILLE PATTERN DOTS-124567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u287B"},10364:{"value":"287C","name":"BRAILLE PATTERN DOTS-34567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u287C"},10365:{"value":"287D","name":"BRAILLE PATTERN DOTS-134567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u287D"},10366:{"value":"287E","name":"BRAILLE PATTERN DOTS-234567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u287E"},10367:{"value":"287F","name":"BRAILLE PATTERN DOTS-1234567","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u287F"},10368:{"value":"2880","name":"BRAILLE PATTERN DOTS-8","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2880"},10369:{"value":"2881","name":"BRAILLE PATTERN DOTS-18","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2881"},10370:{"value":"2882","name":"BRAILLE PATTERN DOTS-28","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2882"},10371:{"value":"2883","name":"BRAILLE PATTERN DOTS-128","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2883"},10372:{"value":"2884","name":"BRAILLE PATTERN DOTS-38","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2884"},10373:{"value":"2885","name":"BRAILLE PATTERN DOTS-138","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2885"},10374:{"value":"2886","name":"BRAILLE PATTERN DOTS-238","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2886"},10375:{"value":"2887","name":"BRAILLE PATTERN DOTS-1238","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2887"},10376:{"value":"2888","name":"BRAILLE PATTERN DOTS-48","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2888"},10377:{"value":"2889","name":"BRAILLE PATTERN DOTS-148","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2889"},10378:{"value":"288A","name":"BRAILLE PATTERN DOTS-248","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u288A"},10379:{"value":"288B","name":"BRAILLE PATTERN DOTS-1248","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u288B"},10380:{"value":"288C","name":"BRAILLE PATTERN DOTS-348","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u288C"},10381:{"value":"288D","name":"BRAILLE PATTERN DOTS-1348","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u288D"},10382:{"value":"288E","name":"BRAILLE PATTERN DOTS-2348","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u288E"},10383:{"value":"288F","name":"BRAILLE PATTERN DOTS-12348","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u288F"},10384:{"value":"2890","name":"BRAILLE PATTERN DOTS-58","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2890"},10385:{"value":"2891","name":"BRAILLE PATTERN DOTS-158","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2891"},10386:{"value":"2892","name":"BRAILLE PATTERN DOTS-258","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2892"},10387:{"value":"2893","name":"BRAILLE PATTERN DOTS-1258","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2893"},10388:{"value":"2894","name":"BRAILLE PATTERN DOTS-358","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2894"},10389:{"value":"2895","name":"BRAILLE PATTERN DOTS-1358","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2895"},10390:{"value":"2896","name":"BRAILLE PATTERN DOTS-2358","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2896"},10391:{"value":"2897","name":"BRAILLE PATTERN DOTS-12358","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2897"},10392:{"value":"2898","name":"BRAILLE PATTERN DOTS-458","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2898"},10393:{"value":"2899","name":"BRAILLE PATTERN DOTS-1458","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2899"},10394:{"value":"289A","name":"BRAILLE PATTERN DOTS-2458","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u289A"},10395:{"value":"289B","name":"BRAILLE PATTERN DOTS-12458","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u289B"},10396:{"value":"289C","name":"BRAILLE PATTERN DOTS-3458","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u289C"},10397:{"value":"289D","name":"BRAILLE PATTERN DOTS-13458","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u289D"},10398:{"value":"289E","name":"BRAILLE PATTERN DOTS-23458","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u289E"},10399:{"value":"289F","name":"BRAILLE PATTERN DOTS-123458","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u289F"},10400:{"value":"28A0","name":"BRAILLE PATTERN DOTS-68","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28A0"},10401:{"value":"28A1","name":"BRAILLE PATTERN DOTS-168","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28A1"},10402:{"value":"28A2","name":"BRAILLE PATTERN DOTS-268","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28A2"},10403:{"value":"28A3","name":"BRAILLE PATTERN DOTS-1268","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28A3"},10404:{"value":"28A4","name":"BRAILLE PATTERN DOTS-368","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28A4"},10405:{"value":"28A5","name":"BRAILLE PATTERN DOTS-1368","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28A5"},10406:{"value":"28A6","name":"BRAILLE PATTERN DOTS-2368","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28A6"},10407:{"value":"28A7","name":"BRAILLE PATTERN DOTS-12368","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28A7"},10408:{"value":"28A8","name":"BRAILLE PATTERN DOTS-468","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28A8"},10409:{"value":"28A9","name":"BRAILLE PATTERN DOTS-1468","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28A9"},10410:{"value":"28AA","name":"BRAILLE PATTERN DOTS-2468","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28AA"},10411:{"value":"28AB","name":"BRAILLE PATTERN DOTS-12468","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28AB"},10412:{"value":"28AC","name":"BRAILLE PATTERN DOTS-3468","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28AC"},10413:{"value":"28AD","name":"BRAILLE PATTERN DOTS-13468","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28AD"},10414:{"value":"28AE","name":"BRAILLE PATTERN DOTS-23468","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28AE"},10415:{"value":"28AF","name":"BRAILLE PATTERN DOTS-123468","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28AF"},10416:{"value":"28B0","name":"BRAILLE PATTERN DOTS-568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28B0"},10417:{"value":"28B1","name":"BRAILLE PATTERN DOTS-1568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28B1"},10418:{"value":"28B2","name":"BRAILLE PATTERN DOTS-2568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28B2"},10419:{"value":"28B3","name":"BRAILLE PATTERN DOTS-12568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28B3"},10420:{"value":"28B4","name":"BRAILLE PATTERN DOTS-3568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28B4"},10421:{"value":"28B5","name":"BRAILLE PATTERN DOTS-13568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28B5"},10422:{"value":"28B6","name":"BRAILLE PATTERN DOTS-23568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28B6"},10423:{"value":"28B7","name":"BRAILLE PATTERN DOTS-123568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28B7"},10424:{"value":"28B8","name":"BRAILLE PATTERN DOTS-4568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28B8"},10425:{"value":"28B9","name":"BRAILLE PATTERN DOTS-14568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28B9"},10426:{"value":"28BA","name":"BRAILLE PATTERN DOTS-24568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28BA"},10427:{"value":"28BB","name":"BRAILLE PATTERN DOTS-124568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28BB"},10428:{"value":"28BC","name":"BRAILLE PATTERN DOTS-34568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28BC"},10429:{"value":"28BD","name":"BRAILLE PATTERN DOTS-134568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28BD"},10430:{"value":"28BE","name":"BRAILLE PATTERN DOTS-234568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28BE"},10431:{"value":"28BF","name":"BRAILLE PATTERN DOTS-1234568","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28BF"},10432:{"value":"28C0","name":"BRAILLE PATTERN DOTS-78","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28C0"},10433:{"value":"28C1","name":"BRAILLE PATTERN DOTS-178","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28C1"},10434:{"value":"28C2","name":"BRAILLE PATTERN DOTS-278","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28C2"},10435:{"value":"28C3","name":"BRAILLE PATTERN DOTS-1278","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28C3"},10436:{"value":"28C4","name":"BRAILLE PATTERN DOTS-378","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28C4"},10437:{"value":"28C5","name":"BRAILLE PATTERN DOTS-1378","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28C5"},10438:{"value":"28C6","name":"BRAILLE PATTERN DOTS-2378","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28C6"},10439:{"value":"28C7","name":"BRAILLE PATTERN DOTS-12378","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28C7"},10440:{"value":"28C8","name":"BRAILLE PATTERN DOTS-478","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28C8"},10441:{"value":"28C9","name":"BRAILLE PATTERN DOTS-1478","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28C9"},10442:{"value":"28CA","name":"BRAILLE PATTERN DOTS-2478","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28CA"},10443:{"value":"28CB","name":"BRAILLE PATTERN DOTS-12478","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28CB"},10444:{"value":"28CC","name":"BRAILLE PATTERN DOTS-3478","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28CC"},10445:{"value":"28CD","name":"BRAILLE PATTERN DOTS-13478","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28CD"},10446:{"value":"28CE","name":"BRAILLE PATTERN DOTS-23478","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28CE"},10447:{"value":"28CF","name":"BRAILLE PATTERN DOTS-123478","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28CF"},10448:{"value":"28D0","name":"BRAILLE PATTERN DOTS-578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28D0"},10449:{"value":"28D1","name":"BRAILLE PATTERN DOTS-1578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28D1"},10450:{"value":"28D2","name":"BRAILLE PATTERN DOTS-2578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28D2"},10451:{"value":"28D3","name":"BRAILLE PATTERN DOTS-12578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28D3"},10452:{"value":"28D4","name":"BRAILLE PATTERN DOTS-3578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28D4"},10453:{"value":"28D5","name":"BRAILLE PATTERN DOTS-13578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28D5"},10454:{"value":"28D6","name":"BRAILLE PATTERN DOTS-23578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28D6"},10455:{"value":"28D7","name":"BRAILLE PATTERN DOTS-123578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28D7"},10456:{"value":"28D8","name":"BRAILLE PATTERN DOTS-4578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28D8"},10457:{"value":"28D9","name":"BRAILLE PATTERN DOTS-14578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28D9"},10458:{"value":"28DA","name":"BRAILLE PATTERN DOTS-24578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28DA"},10459:{"value":"28DB","name":"BRAILLE PATTERN DOTS-124578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28DB"},10460:{"value":"28DC","name":"BRAILLE PATTERN DOTS-34578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28DC"},10461:{"value":"28DD","name":"BRAILLE PATTERN DOTS-134578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28DD"},10462:{"value":"28DE","name":"BRAILLE PATTERN DOTS-234578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28DE"},10463:{"value":"28DF","name":"BRAILLE PATTERN DOTS-1234578","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28DF"},10464:{"value":"28E0","name":"BRAILLE PATTERN DOTS-678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28E0"},10465:{"value":"28E1","name":"BRAILLE PATTERN DOTS-1678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28E1"},10466:{"value":"28E2","name":"BRAILLE PATTERN DOTS-2678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28E2"},10467:{"value":"28E3","name":"BRAILLE PATTERN DOTS-12678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28E3"},10468:{"value":"28E4","name":"BRAILLE PATTERN DOTS-3678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28E4"},10469:{"value":"28E5","name":"BRAILLE PATTERN DOTS-13678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28E5"},10470:{"value":"28E6","name":"BRAILLE PATTERN DOTS-23678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28E6"},10471:{"value":"28E7","name":"BRAILLE PATTERN DOTS-123678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28E7"},10472:{"value":"28E8","name":"BRAILLE PATTERN DOTS-4678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28E8"},10473:{"value":"28E9","name":"BRAILLE PATTERN DOTS-14678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28E9"},10474:{"value":"28EA","name":"BRAILLE PATTERN DOTS-24678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28EA"},10475:{"value":"28EB","name":"BRAILLE PATTERN DOTS-124678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28EB"},10476:{"value":"28EC","name":"BRAILLE PATTERN DOTS-34678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28EC"},10477:{"value":"28ED","name":"BRAILLE PATTERN DOTS-134678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28ED"},10478:{"value":"28EE","name":"BRAILLE PATTERN DOTS-234678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28EE"},10479:{"value":"28EF","name":"BRAILLE PATTERN DOTS-1234678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28EF"},10480:{"value":"28F0","name":"BRAILLE PATTERN DOTS-5678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28F0"},10481:{"value":"28F1","name":"BRAILLE PATTERN DOTS-15678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28F1"},10482:{"value":"28F2","name":"BRAILLE PATTERN DOTS-25678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28F2"},10483:{"value":"28F3","name":"BRAILLE PATTERN DOTS-125678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28F3"},10484:{"value":"28F4","name":"BRAILLE PATTERN DOTS-35678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28F4"},10485:{"value":"28F5","name":"BRAILLE PATTERN DOTS-135678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28F5"},10486:{"value":"28F6","name":"BRAILLE PATTERN DOTS-235678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28F6"},10487:{"value":"28F7","name":"BRAILLE PATTERN DOTS-1235678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28F7"},10488:{"value":"28F8","name":"BRAILLE PATTERN DOTS-45678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28F8"},10489:{"value":"28F9","name":"BRAILLE PATTERN DOTS-145678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28F9"},10490:{"value":"28FA","name":"BRAILLE PATTERN DOTS-245678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28FA"},10491:{"value":"28FB","name":"BRAILLE PATTERN DOTS-1245678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28FB"},10492:{"value":"28FC","name":"BRAILLE PATTERN DOTS-345678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28FC"},10493:{"value":"28FD","name":"BRAILLE PATTERN DOTS-1345678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28FD"},10494:{"value":"28FE","name":"BRAILLE PATTERN DOTS-2345678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28FE"},10495:{"value":"28FF","name":"BRAILLE PATTERN DOTS-12345678","category":"So","class":"0","bidirectional_category":"L","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u28FF"},11008:{"value":"2B00","name":"NORTH EAST WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B00"},11009:{"value":"2B01","name":"NORTH WEST WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B01"},11010:{"value":"2B02","name":"SOUTH EAST WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B02"},11011:{"value":"2B03","name":"SOUTH WEST WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B03"},11012:{"value":"2B04","name":"LEFT RIGHT WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B04"},11013:{"value":"2B05","name":"LEFTWARDS BLACK ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B05"},11014:{"value":"2B06","name":"UPWARDS BLACK ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B06"},11015:{"value":"2B07","name":"DOWNWARDS BLACK ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B07"},11016:{"value":"2B08","name":"NORTH EAST BLACK ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B08"},11017:{"value":"2B09","name":"NORTH WEST BLACK ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B09"},11018:{"value":"2B0A","name":"SOUTH EAST BLACK ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B0A"},11019:{"value":"2B0B","name":"SOUTH WEST BLACK ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B0B"},11020:{"value":"2B0C","name":"LEFT RIGHT BLACK ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B0C"},11021:{"value":"2B0D","name":"UP DOWN BLACK ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B0D"},11022:{"value":"2B0E","name":"RIGHTWARDS ARROW WITH TIP DOWNWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B0E"},11023:{"value":"2B0F","name":"RIGHTWARDS ARROW WITH TIP UPWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B0F"},11024:{"value":"2B10","name":"LEFTWARDS ARROW WITH TIP DOWNWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B10"},11025:{"value":"2B11","name":"LEFTWARDS ARROW WITH TIP UPWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B11"},11026:{"value":"2B12","name":"SQUARE WITH TOP HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B12"},11027:{"value":"2B13","name":"SQUARE WITH BOTTOM HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B13"},11028:{"value":"2B14","name":"SQUARE WITH UPPER RIGHT DIAGONAL HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B14"},11029:{"value":"2B15","name":"SQUARE WITH LOWER LEFT DIAGONAL HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B15"},11030:{"value":"2B16","name":"DIAMOND WITH LEFT HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B16"},11031:{"value":"2B17","name":"DIAMOND WITH RIGHT HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B17"},11032:{"value":"2B18","name":"DIAMOND WITH TOP HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B18"},11033:{"value":"2B19","name":"DIAMOND WITH BOTTOM HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B19"},11034:{"value":"2B1A","name":"DOTTED SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B1A"},11035:{"value":"2B1B","name":"BLACK LARGE SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B1B"},11036:{"value":"2B1C","name":"WHITE LARGE SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B1C"},11037:{"value":"2B1D","name":"BLACK VERY SMALL SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B1D"},11038:{"value":"2B1E","name":"WHITE VERY SMALL SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B1E"},11039:{"value":"2B1F","name":"BLACK PENTAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B1F"},11040:{"value":"2B20","name":"WHITE PENTAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B20"},11041:{"value":"2B21","name":"WHITE HEXAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B21"},11042:{"value":"2B22","name":"BLACK HEXAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B22"},11043:{"value":"2B23","name":"HORIZONTAL BLACK HEXAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B23"},11044:{"value":"2B24","name":"BLACK LARGE CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B24"},11045:{"value":"2B25","name":"BLACK MEDIUM DIAMOND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B25"},11046:{"value":"2B26","name":"WHITE MEDIUM DIAMOND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B26"},11047:{"value":"2B27","name":"BLACK MEDIUM LOZENGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B27"},11048:{"value":"2B28","name":"WHITE MEDIUM LOZENGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B28"},11049:{"value":"2B29","name":"BLACK SMALL DIAMOND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B29"},11050:{"value":"2B2A","name":"BLACK SMALL LOZENGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B2A"},11051:{"value":"2B2B","name":"WHITE SMALL LOZENGE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B2B"},11052:{"value":"2B2C","name":"BLACK HORIZONTAL ELLIPSE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B2C"},11053:{"value":"2B2D","name":"WHITE HORIZONTAL ELLIPSE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B2D"},11054:{"value":"2B2E","name":"BLACK VERTICAL ELLIPSE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B2E"},11055:{"value":"2B2F","name":"WHITE VERTICAL ELLIPSE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B2F"},11077:{"value":"2B45","name":"LEFTWARDS QUADRUPLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B45"},11078:{"value":"2B46","name":"RIGHTWARDS QUADRUPLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B46"},11085:{"value":"2B4D","name":"DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B4D"},11086:{"value":"2B4E","name":"SHORT SLANTED NORTH ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B4E"},11087:{"value":"2B4F","name":"SHORT BACKSLANTED SOUTH ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B4F"},11088:{"value":"2B50","name":"WHITE MEDIUM STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B50"},11089:{"value":"2B51","name":"BLACK SMALL STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B51"},11090:{"value":"2B52","name":"WHITE SMALL STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B52"},11091:{"value":"2B53","name":"BLACK RIGHT-POINTING PENTAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B53"},11092:{"value":"2B54","name":"WHITE RIGHT-POINTING PENTAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B54"},11093:{"value":"2B55","name":"HEAVY LARGE CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B55"},11094:{"value":"2B56","name":"HEAVY OVAL WITH OVAL INSIDE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B56"},11095:{"value":"2B57","name":"HEAVY CIRCLE WITH CIRCLE INSIDE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B57"},11096:{"value":"2B58","name":"HEAVY CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B58"},11097:{"value":"2B59","name":"HEAVY CIRCLED SALTIRE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B59"},11098:{"value":"2B5A","name":"SLANTED NORTH ARROW WITH HOOKED HEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B5A"},11099:{"value":"2B5B","name":"BACKSLANTED SOUTH ARROW WITH HOOKED TAIL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B5B"},11100:{"value":"2B5C","name":"SLANTED NORTH ARROW WITH HORIZONTAL TAIL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B5C"},11101:{"value":"2B5D","name":"BACKSLANTED SOUTH ARROW WITH HORIZONTAL TAIL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B5D"},11102:{"value":"2B5E","name":"BENT ARROW POINTING DOWNWARDS THEN NORTH EAST","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B5E"},11103:{"value":"2B5F","name":"SHORT BENT ARROW POINTING DOWNWARDS THEN NORTH EAST","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B5F"},11104:{"value":"2B60","name":"LEFTWARDS TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B60"},11105:{"value":"2B61","name":"UPWARDS TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B61"},11106:{"value":"2B62","name":"RIGHTWARDS TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B62"},11107:{"value":"2B63","name":"DOWNWARDS TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B63"},11108:{"value":"2B64","name":"LEFT RIGHT TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B64"},11109:{"value":"2B65","name":"UP DOWN TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B65"},11110:{"value":"2B66","name":"NORTH WEST TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B66"},11111:{"value":"2B67","name":"NORTH EAST TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B67"},11112:{"value":"2B68","name":"SOUTH EAST TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B68"},11113:{"value":"2B69","name":"SOUTH WEST TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B69"},11114:{"value":"2B6A","name":"LEFTWARDS TRIANGLE-HEADED DASHED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B6A"},11115:{"value":"2B6B","name":"UPWARDS TRIANGLE-HEADED DASHED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B6B"},11116:{"value":"2B6C","name":"RIGHTWARDS TRIANGLE-HEADED DASHED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B6C"},11117:{"value":"2B6D","name":"DOWNWARDS TRIANGLE-HEADED DASHED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B6D"},11118:{"value":"2B6E","name":"CLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B6E"},11119:{"value":"2B6F","name":"ANTICLOCKWISE TRIANGLE-HEADED OPEN CIRCLE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B6F"},11120:{"value":"2B70","name":"LEFTWARDS TRIANGLE-HEADED ARROW TO BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B70"},11121:{"value":"2B71","name":"UPWARDS TRIANGLE-HEADED ARROW TO BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B71"},11122:{"value":"2B72","name":"RIGHTWARDS TRIANGLE-HEADED ARROW TO BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B72"},11123:{"value":"2B73","name":"DOWNWARDS TRIANGLE-HEADED ARROW TO BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B73"},11126:{"value":"2B76","name":"NORTH WEST TRIANGLE-HEADED ARROW TO BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B76"},11127:{"value":"2B77","name":"NORTH EAST TRIANGLE-HEADED ARROW TO BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B77"},11128:{"value":"2B78","name":"SOUTH EAST TRIANGLE-HEADED ARROW TO BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B78"},11129:{"value":"2B79","name":"SOUTH WEST TRIANGLE-HEADED ARROW TO BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B79"},11130:{"value":"2B7A","name":"LEFTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B7A"},11131:{"value":"2B7B","name":"UPWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B7B"},11132:{"value":"2B7C","name":"RIGHTWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B7C"},11133:{"value":"2B7D","name":"DOWNWARDS TRIANGLE-HEADED ARROW WITH DOUBLE HORIZONTAL STROKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B7D"},11134:{"value":"2B7E","name":"HORIZONTAL TAB KEY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B7E"},11135:{"value":"2B7F","name":"VERTICAL TAB KEY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B7F"},11136:{"value":"2B80","name":"LEFTWARDS TRIANGLE-HEADED ARROW OVER RIGHTWARDS TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B80"},11137:{"value":"2B81","name":"UPWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF DOWNWARDS TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B81"},11138:{"value":"2B82","name":"RIGHTWARDS TRIANGLE-HEADED ARROW OVER LEFTWARDS TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B82"},11139:{"value":"2B83","name":"DOWNWARDS TRIANGLE-HEADED ARROW LEFTWARDS OF UPWARDS TRIANGLE-HEADED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B83"},11140:{"value":"2B84","name":"LEFTWARDS TRIANGLE-HEADED PAIRED ARROWS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B84"},11141:{"value":"2B85","name":"UPWARDS TRIANGLE-HEADED PAIRED ARROWS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B85"},11142:{"value":"2B86","name":"RIGHTWARDS TRIANGLE-HEADED PAIRED ARROWS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B86"},11143:{"value":"2B87","name":"DOWNWARDS TRIANGLE-HEADED PAIRED ARROWS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B87"},11144:{"value":"2B88","name":"LEFTWARDS BLACK CIRCLED WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B88"},11145:{"value":"2B89","name":"UPWARDS BLACK CIRCLED WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B89"},11146:{"value":"2B8A","name":"RIGHTWARDS BLACK CIRCLED WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B8A"},11147:{"value":"2B8B","name":"DOWNWARDS BLACK CIRCLED WHITE ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B8B"},11148:{"value":"2B8C","name":"ANTICLOCKWISE TRIANGLE-HEADED RIGHT U-SHAPED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B8C"},11149:{"value":"2B8D","name":"ANTICLOCKWISE TRIANGLE-HEADED BOTTOM U-SHAPED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B8D"},11150:{"value":"2B8E","name":"ANTICLOCKWISE TRIANGLE-HEADED LEFT U-SHAPED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B8E"},11151:{"value":"2B8F","name":"ANTICLOCKWISE TRIANGLE-HEADED TOP U-SHAPED ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B8F"},11152:{"value":"2B90","name":"RETURN LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B90"},11153:{"value":"2B91","name":"RETURN RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B91"},11154:{"value":"2B92","name":"NEWLINE LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B92"},11155:{"value":"2B93","name":"NEWLINE RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B93"},11156:{"value":"2B94","name":"FOUR CORNER ARROWS CIRCLING ANTICLOCKWISE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B94"},11157:{"value":"2B95","name":"RIGHTWARDS BLACK ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B95"},11160:{"value":"2B98","name":"THREE-D TOP-LIGHTED LEFTWARDS EQUILATERAL ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B98"},11161:{"value":"2B99","name":"THREE-D RIGHT-LIGHTED UPWARDS EQUILATERAL ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B99"},11162:{"value":"2B9A","name":"THREE-D TOP-LIGHTED RIGHTWARDS EQUILATERAL ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B9A"},11163:{"value":"2B9B","name":"THREE-D LEFT-LIGHTED DOWNWARDS EQUILATERAL ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B9B"},11164:{"value":"2B9C","name":"BLACK LEFTWARDS EQUILATERAL ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B9C"},11165:{"value":"2B9D","name":"BLACK UPWARDS EQUILATERAL ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B9D"},11166:{"value":"2B9E","name":"BLACK RIGHTWARDS EQUILATERAL ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B9E"},11167:{"value":"2B9F","name":"BLACK DOWNWARDS EQUILATERAL ARROWHEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2B9F"},11168:{"value":"2BA0","name":"DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BA0"},11169:{"value":"2BA1","name":"DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BA1"},11170:{"value":"2BA2","name":"UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP LEFTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BA2"},11171:{"value":"2BA3","name":"UPWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BA3"},11172:{"value":"2BA4","name":"LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BA4"},11173:{"value":"2BA5","name":"RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP UPWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BA5"},11174:{"value":"2BA6","name":"LEFTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BA6"},11175:{"value":"2BA7","name":"RIGHTWARDS TRIANGLE-HEADED ARROW WITH LONG TIP DOWNWARDS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BA7"},11176:{"value":"2BA8","name":"BLACK CURVED DOWNWARDS AND LEFTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BA8"},11177:{"value":"2BA9","name":"BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BA9"},11178:{"value":"2BAA","name":"BLACK CURVED UPWARDS AND LEFTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BAA"},11179:{"value":"2BAB","name":"BLACK CURVED UPWARDS AND RIGHTWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BAB"},11180:{"value":"2BAC","name":"BLACK CURVED LEFTWARDS AND UPWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BAC"},11181:{"value":"2BAD","name":"BLACK CURVED RIGHTWARDS AND UPWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BAD"},11182:{"value":"2BAE","name":"BLACK CURVED LEFTWARDS AND DOWNWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BAE"},11183:{"value":"2BAF","name":"BLACK CURVED RIGHTWARDS AND DOWNWARDS ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BAF"},11184:{"value":"2BB0","name":"RIBBON ARROW DOWN LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BB0"},11185:{"value":"2BB1","name":"RIBBON ARROW DOWN RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BB1"},11186:{"value":"2BB2","name":"RIBBON ARROW UP LEFT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BB2"},11187:{"value":"2BB3","name":"RIBBON ARROW UP RIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BB3"},11188:{"value":"2BB4","name":"RIBBON ARROW LEFT UP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BB4"},11189:{"value":"2BB5","name":"RIBBON ARROW RIGHT UP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BB5"},11190:{"value":"2BB6","name":"RIBBON ARROW LEFT DOWN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BB6"},11191:{"value":"2BB7","name":"RIBBON ARROW RIGHT DOWN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BB7"},11192:{"value":"2BB8","name":"UPWARDS WHITE ARROW FROM BAR WITH HORIZONTAL BAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BB8"},11193:{"value":"2BB9","name":"UP ARROWHEAD IN A RECTANGLE BOX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BB9"},11194:{"value":"2BBA","name":"OVERLAPPING WHITE SQUARES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BBA"},11195:{"value":"2BBB","name":"OVERLAPPING WHITE AND BLACK SQUARES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BBB"},11196:{"value":"2BBC","name":"OVERLAPPING BLACK SQUARES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BBC"},11197:{"value":"2BBD","name":"BALLOT BOX WITH LIGHT X","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BBD"},11198:{"value":"2BBE","name":"CIRCLED X","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BBE"},11199:{"value":"2BBF","name":"CIRCLED BOLD X","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BBF"},11200:{"value":"2BC0","name":"BLACK SQUARE CENTRED","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BC0"},11201:{"value":"2BC1","name":"BLACK DIAMOND CENTRED","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BC1"},11202:{"value":"2BC2","name":"TURNED BLACK PENTAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BC2"},11203:{"value":"2BC3","name":"HORIZONTAL BLACK OCTAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BC3"},11204:{"value":"2BC4","name":"BLACK OCTAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BC4"},11205:{"value":"2BC5","name":"BLACK MEDIUM UP-POINTING TRIANGLE CENTRED","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BC5"},11206:{"value":"2BC6","name":"BLACK MEDIUM DOWN-POINTING TRIANGLE CENTRED","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BC6"},11207:{"value":"2BC7","name":"BLACK MEDIUM LEFT-POINTING TRIANGLE CENTRED","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BC7"},11208:{"value":"2BC8","name":"BLACK MEDIUM RIGHT-POINTING TRIANGLE CENTRED","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BC8"},11209:{"value":"2BC9","name":"NEPTUNE FORM TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BC9"},11210:{"value":"2BCA","name":"TOP HALF BLACK CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BCA"},11211:{"value":"2BCB","name":"BOTTOM HALF BLACK CIRCLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BCB"},11212:{"value":"2BCC","name":"LIGHT FOUR POINTED BLACK CUSP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BCC"},11213:{"value":"2BCD","name":"ROTATED LIGHT FOUR POINTED BLACK CUSP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BCD"},11214:{"value":"2BCE","name":"WHITE FOUR POINTED CUSP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BCE"},11215:{"value":"2BCF","name":"ROTATED WHITE FOUR POINTED CUSP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BCF"},11216:{"value":"2BD0","name":"SQUARE POSITION INDICATOR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BD0"},11217:{"value":"2BD1","name":"UNCERTAINTY SIGN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BD1"},11218:{"value":"2BD2","name":"GROUP MARK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BD2"},11219:{"value":"2BD3","name":"PLUTO FORM TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BD3"},11220:{"value":"2BD4","name":"PLUTO FORM THREE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BD4"},11221:{"value":"2BD5","name":"PLUTO FORM FOUR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BD5"},11222:{"value":"2BD6","name":"PLUTO FORM FIVE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BD6"},11223:{"value":"2BD7","name":"TRANSPLUTO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BD7"},11224:{"value":"2BD8","name":"PROSERPINA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BD8"},11225:{"value":"2BD9","name":"ASTRAEA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BD9"},11226:{"value":"2BDA","name":"HYGIEA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BDA"},11227:{"value":"2BDB","name":"PHOLUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BDB"},11228:{"value":"2BDC","name":"NESSUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BDC"},11229:{"value":"2BDD","name":"WHITE MOON SELENA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BDD"},11230:{"value":"2BDE","name":"BLACK DIAMOND ON CROSS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BDE"},11231:{"value":"2BDF","name":"TRUE LIGHT MOON ARTA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BDF"},11232:{"value":"2BE0","name":"CUPIDO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BE0"},11233:{"value":"2BE1","name":"HADES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BE1"},11234:{"value":"2BE2","name":"ZEUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BE2"},11235:{"value":"2BE3","name":"KRONOS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BE3"},11236:{"value":"2BE4","name":"APOLLON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BE4"},11237:{"value":"2BE5","name":"ADMETOS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BE5"},11238:{"value":"2BE6","name":"VULCANUS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BE6"},11239:{"value":"2BE7","name":"POSEIDON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BE7"},11240:{"value":"2BE8","name":"LEFT HALF BLACK STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BE8"},11241:{"value":"2BE9","name":"RIGHT HALF BLACK STAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BE9"},11242:{"value":"2BEA","name":"STAR WITH LEFT HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BEA"},11243:{"value":"2BEB","name":"STAR WITH RIGHT HALF BLACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BEB"},11244:{"value":"2BEC","name":"LEFTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BEC"},11245:{"value":"2BED","name":"UPWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BED"},11246:{"value":"2BEE","name":"RIGHTWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BEE"},11247:{"value":"2BEF","name":"DOWNWARDS TWO-HEADED ARROW WITH TRIANGLE ARROWHEADS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BEF"},11248:{"value":"2BF0","name":"ERIS FORM ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BF0"},11249:{"value":"2BF1","name":"ERIS FORM TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BF1"},11250:{"value":"2BF2","name":"SEDNA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BF2"},11251:{"value":"2BF3","name":"RUSSIAN ASTROLOGICAL SYMBOL VIGINTILE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BF3"},11252:{"value":"2BF4","name":"RUSSIAN ASTROLOGICAL SYMBOL NOVILE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BF4"},11253:{"value":"2BF5","name":"RUSSIAN ASTROLOGICAL SYMBOL QUINTILE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BF5"},11254:{"value":"2BF6","name":"RUSSIAN ASTROLOGICAL SYMBOL BINOVILE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BF6"},11255:{"value":"2BF7","name":"RUSSIAN ASTROLOGICAL SYMBOL SENTAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BF7"},11256:{"value":"2BF8","name":"RUSSIAN ASTROLOGICAL SYMBOL TREDECILE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BF8"},11257:{"value":"2BF9","name":"EQUALS SIGN WITH INFINITY BELOW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BF9"},11258:{"value":"2BFA","name":"UNITED SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BFA"},11259:{"value":"2BFB","name":"SEPARATED SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BFB"},11260:{"value":"2BFC","name":"DOUBLED SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BFC"},11261:{"value":"2BFD","name":"PASSED SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BFD"},11262:{"value":"2BFE","name":"REVERSED RIGHT ANGLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"Y","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BFE"},11263:{"value":"2BFF","name":"HELLSCHREIBER PAUSE SYMBOL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2BFF"},11493:{"value":"2CE5","name":"COPTIC SYMBOL MI RO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2CE5"},11494:{"value":"2CE6","name":"COPTIC SYMBOL PI RO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2CE6"},11495:{"value":"2CE7","name":"COPTIC SYMBOL STAUROS","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2CE7"},11496:{"value":"2CE8","name":"COPTIC SYMBOL TAU RO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2CE8"},11497:{"value":"2CE9","name":"COPTIC SYMBOL KHI RO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2CE9"},11498:{"value":"2CEA","name":"COPTIC SYMBOL SHIMA SIMA","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2CEA"},11904:{"value":"2E80","name":"CJK RADICAL REPEAT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E80"},11905:{"value":"2E81","name":"CJK RADICAL CLIFF","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E81"},11906:{"value":"2E82","name":"CJK RADICAL SECOND ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E82"},11907:{"value":"2E83","name":"CJK RADICAL SECOND TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E83"},11908:{"value":"2E84","name":"CJK RADICAL SECOND THREE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E84"},11909:{"value":"2E85","name":"CJK RADICAL PERSON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E85"},11910:{"value":"2E86","name":"CJK RADICAL BOX","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E86"},11911:{"value":"2E87","name":"CJK RADICAL TABLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E87"},11912:{"value":"2E88","name":"CJK RADICAL KNIFE ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E88"},11913:{"value":"2E89","name":"CJK RADICAL KNIFE TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E89"},11914:{"value":"2E8A","name":"CJK RADICAL DIVINATION","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E8A"},11915:{"value":"2E8B","name":"CJK RADICAL SEAL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E8B"},11916:{"value":"2E8C","name":"CJK RADICAL SMALL ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E8C"},11917:{"value":"2E8D","name":"CJK RADICAL SMALL TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E8D"},11918:{"value":"2E8E","name":"CJK RADICAL LAME ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E8E"},11919:{"value":"2E8F","name":"CJK RADICAL LAME TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E8F"},11920:{"value":"2E90","name":"CJK RADICAL LAME THREE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E90"},11921:{"value":"2E91","name":"CJK RADICAL LAME FOUR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E91"},11922:{"value":"2E92","name":"CJK RADICAL SNAKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E92"},11923:{"value":"2E93","name":"CJK RADICAL THREAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E93"},11924:{"value":"2E94","name":"CJK RADICAL SNOUT ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E94"},11925:{"value":"2E95","name":"CJK RADICAL SNOUT TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E95"},11926:{"value":"2E96","name":"CJK RADICAL HEART ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E96"},11927:{"value":"2E97","name":"CJK RADICAL HEART TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E97"},11928:{"value":"2E98","name":"CJK RADICAL HAND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E98"},11929:{"value":"2E99","name":"CJK RADICAL RAP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E99"},11931:{"value":"2E9B","name":"CJK RADICAL CHOKE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E9B"},11932:{"value":"2E9C","name":"CJK RADICAL SUN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E9C"},11933:{"value":"2E9D","name":"CJK RADICAL MOON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E9D"},11934:{"value":"2E9E","name":"CJK RADICAL DEATH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E9E"},11935:{"value":"2E9F","name":"CJK RADICAL MOTHER","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6BCD","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2E9F"},11936:{"value":"2EA0","name":"CJK RADICAL CIVILIAN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EA0"},11937:{"value":"2EA1","name":"CJK RADICAL WATER ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EA1"},11938:{"value":"2EA2","name":"CJK RADICAL WATER TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EA2"},11939:{"value":"2EA3","name":"CJK RADICAL FIRE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EA3"},11940:{"value":"2EA4","name":"CJK RADICAL PAW ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EA4"},11941:{"value":"2EA5","name":"CJK RADICAL PAW TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EA5"},11942:{"value":"2EA6","name":"CJK RADICAL SIMPLIFIED HALF TREE TRUNK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EA6"},11943:{"value":"2EA7","name":"CJK RADICAL COW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EA7"},11944:{"value":"2EA8","name":"CJK RADICAL DOG","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EA8"},11945:{"value":"2EA9","name":"CJK RADICAL JADE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EA9"},11946:{"value":"2EAA","name":"CJK RADICAL BOLT OF CLOTH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EAA"},11947:{"value":"2EAB","name":"CJK RADICAL EYE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EAB"},11948:{"value":"2EAC","name":"CJK RADICAL SPIRIT ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EAC"},11949:{"value":"2EAD","name":"CJK RADICAL SPIRIT TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EAD"},11950:{"value":"2EAE","name":"CJK RADICAL BAMBOO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EAE"},11951:{"value":"2EAF","name":"CJK RADICAL SILK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EAF"},11952:{"value":"2EB0","name":"CJK RADICAL C-SIMPLIFIED SILK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EB0"},11953:{"value":"2EB1","name":"CJK RADICAL NET ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EB1"},11954:{"value":"2EB2","name":"CJK RADICAL NET TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EB2"},11955:{"value":"2EB3","name":"CJK RADICAL NET THREE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EB3"},11956:{"value":"2EB4","name":"CJK RADICAL NET FOUR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EB4"},11957:{"value":"2EB5","name":"CJK RADICAL MESH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EB5"},11958:{"value":"2EB6","name":"CJK RADICAL SHEEP","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EB6"},11959:{"value":"2EB7","name":"CJK RADICAL RAM","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EB7"},11960:{"value":"2EB8","name":"CJK RADICAL EWE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EB8"},11961:{"value":"2EB9","name":"CJK RADICAL OLD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EB9"},11962:{"value":"2EBA","name":"CJK RADICAL BRUSH ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EBA"},11963:{"value":"2EBB","name":"CJK RADICAL BRUSH TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EBB"},11964:{"value":"2EBC","name":"CJK RADICAL MEAT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EBC"},11965:{"value":"2EBD","name":"CJK RADICAL MORTAR","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EBD"},11966:{"value":"2EBE","name":"CJK RADICAL GRASS ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EBE"},11967:{"value":"2EBF","name":"CJK RADICAL GRASS TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EBF"},11968:{"value":"2EC0","name":"CJK RADICAL GRASS THREE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EC0"},11969:{"value":"2EC1","name":"CJK RADICAL TIGER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EC1"},11970:{"value":"2EC2","name":"CJK RADICAL CLOTHES","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EC2"},11971:{"value":"2EC3","name":"CJK RADICAL WEST ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EC3"},11972:{"value":"2EC4","name":"CJK RADICAL WEST TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EC4"},11973:{"value":"2EC5","name":"CJK RADICAL C-SIMPLIFIED SEE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EC5"},11974:{"value":"2EC6","name":"CJK RADICAL SIMPLIFIED HORN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EC6"},11975:{"value":"2EC7","name":"CJK RADICAL HORN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EC7"},11976:{"value":"2EC8","name":"CJK RADICAL C-SIMPLIFIED SPEECH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EC8"},11977:{"value":"2EC9","name":"CJK RADICAL C-SIMPLIFIED SHELL","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EC9"},11978:{"value":"2ECA","name":"CJK RADICAL FOOT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ECA"},11979:{"value":"2ECB","name":"CJK RADICAL C-SIMPLIFIED CART","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ECB"},11980:{"value":"2ECC","name":"CJK RADICAL SIMPLIFIED WALK","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ECC"},11981:{"value":"2ECD","name":"CJK RADICAL WALK ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ECD"},11982:{"value":"2ECE","name":"CJK RADICAL WALK TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ECE"},11983:{"value":"2ECF","name":"CJK RADICAL CITY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ECF"},11984:{"value":"2ED0","name":"CJK RADICAL C-SIMPLIFIED GOLD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ED0"},11985:{"value":"2ED1","name":"CJK RADICAL LONG ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ED1"},11986:{"value":"2ED2","name":"CJK RADICAL LONG TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ED2"},11987:{"value":"2ED3","name":"CJK RADICAL C-SIMPLIFIED LONG","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ED3"},11988:{"value":"2ED4","name":"CJK RADICAL C-SIMPLIFIED GATE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ED4"},11989:{"value":"2ED5","name":"CJK RADICAL MOUND ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ED5"},11990:{"value":"2ED6","name":"CJK RADICAL MOUND TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ED6"},11991:{"value":"2ED7","name":"CJK RADICAL RAIN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ED7"},11992:{"value":"2ED8","name":"CJK RADICAL BLUE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ED8"},11993:{"value":"2ED9","name":"CJK RADICAL C-SIMPLIFIED TANNED LEATHER","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2ED9"},11994:{"value":"2EDA","name":"CJK RADICAL C-SIMPLIFIED LEAF","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EDA"},11995:{"value":"2EDB","name":"CJK RADICAL C-SIMPLIFIED WIND","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EDB"},11996:{"value":"2EDC","name":"CJK RADICAL C-SIMPLIFIED FLY","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EDC"},11997:{"value":"2EDD","name":"CJK RADICAL EAT ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EDD"},11998:{"value":"2EDE","name":"CJK RADICAL EAT TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EDE"},11999:{"value":"2EDF","name":"CJK RADICAL EAT THREE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EDF"},12000:{"value":"2EE0","name":"CJK RADICAL C-SIMPLIFIED EAT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EE0"},12001:{"value":"2EE1","name":"CJK RADICAL HEAD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EE1"},12002:{"value":"2EE2","name":"CJK RADICAL C-SIMPLIFIED HORSE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EE2"},12003:{"value":"2EE3","name":"CJK RADICAL BONE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EE3"},12004:{"value":"2EE4","name":"CJK RADICAL GHOST","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EE4"},12005:{"value":"2EE5","name":"CJK RADICAL C-SIMPLIFIED FISH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EE5"},12006:{"value":"2EE6","name":"CJK RADICAL C-SIMPLIFIED BIRD","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EE6"},12007:{"value":"2EE7","name":"CJK RADICAL C-SIMPLIFIED SALT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EE7"},12008:{"value":"2EE8","name":"CJK RADICAL SIMPLIFIED WHEAT","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EE8"},12009:{"value":"2EE9","name":"CJK RADICAL SIMPLIFIED YELLOW","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EE9"},12010:{"value":"2EEA","name":"CJK RADICAL C-SIMPLIFIED FROG","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EEA"},12011:{"value":"2EEB","name":"CJK RADICAL J-SIMPLIFIED EVEN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EEB"},12012:{"value":"2EEC","name":"CJK RADICAL C-SIMPLIFIED EVEN","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EEC"},12013:{"value":"2EED","name":"CJK RADICAL J-SIMPLIFIED TOOTH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EED"},12014:{"value":"2EEE","name":"CJK RADICAL C-SIMPLIFIED TOOTH","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EEE"},12015:{"value":"2EEF","name":"CJK RADICAL J-SIMPLIFIED DRAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EEF"},12016:{"value":"2EF0","name":"CJK RADICAL C-SIMPLIFIED DRAGON","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EF0"},12017:{"value":"2EF1","name":"CJK RADICAL TURTLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EF1"},12018:{"value":"2EF2","name":"CJK RADICAL J-SIMPLIFIED TURTLE","category":"So","class":"0","bidirectional_category":"ON","mapping":"","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EF2"},12019:{"value":"2EF3","name":"CJK RADICAL C-SIMPLIFIED TURTLE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 9F9F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2EF3"},12032:{"value":"2F00","name":"KANGXI RADICAL ONE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 4E00","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F00"},12033:{"value":"2F01","name":"KANGXI RADICAL LINE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 4E28","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F01"},12034:{"value":"2F02","name":"KANGXI RADICAL DOT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 4E36","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F02"},12035:{"value":"2F03","name":"KANGXI RADICAL SLASH","category":"So","class":"0","bidirectional_category":"ON","mapping":" 4E3F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F03"},12036:{"value":"2F04","name":"KANGXI RADICAL SECOND","category":"So","class":"0","bidirectional_category":"ON","mapping":" 4E59","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F04"},12037:{"value":"2F05","name":"KANGXI RADICAL HOOK","category":"So","class":"0","bidirectional_category":"ON","mapping":" 4E85","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F05"},12038:{"value":"2F06","name":"KANGXI RADICAL TWO","category":"So","class":"0","bidirectional_category":"ON","mapping":" 4E8C","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F06"},12039:{"value":"2F07","name":"KANGXI RADICAL LID","category":"So","class":"0","bidirectional_category":"ON","mapping":" 4EA0","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F07"},12040:{"value":"2F08","name":"KANGXI RADICAL MAN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 4EBA","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F08"},12041:{"value":"2F09","name":"KANGXI RADICAL LEGS","category":"So","class":"0","bidirectional_category":"ON","mapping":" 513F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F09"},12042:{"value":"2F0A","name":"KANGXI RADICAL ENTER","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5165","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F0A"},12043:{"value":"2F0B","name":"KANGXI RADICAL EIGHT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 516B","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F0B"},12044:{"value":"2F0C","name":"KANGXI RADICAL DOWN BOX","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5182","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F0C"},12045:{"value":"2F0D","name":"KANGXI RADICAL COVER","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5196","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F0D"},12046:{"value":"2F0E","name":"KANGXI RADICAL ICE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 51AB","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F0E"},12047:{"value":"2F0F","name":"KANGXI RADICAL TABLE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 51E0","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F0F"},12048:{"value":"2F10","name":"KANGXI RADICAL OPEN BOX","category":"So","class":"0","bidirectional_category":"ON","mapping":" 51F5","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F10"},12049:{"value":"2F11","name":"KANGXI RADICAL KNIFE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5200","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F11"},12050:{"value":"2F12","name":"KANGXI RADICAL POWER","category":"So","class":"0","bidirectional_category":"ON","mapping":" 529B","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F12"},12051:{"value":"2F13","name":"KANGXI RADICAL WRAP","category":"So","class":"0","bidirectional_category":"ON","mapping":" 52F9","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F13"},12052:{"value":"2F14","name":"KANGXI RADICAL SPOON","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5315","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F14"},12053:{"value":"2F15","name":"KANGXI RADICAL RIGHT OPEN BOX","category":"So","class":"0","bidirectional_category":"ON","mapping":" 531A","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F15"},12054:{"value":"2F16","name":"KANGXI RADICAL HIDING ENCLOSURE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5338","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F16"},12055:{"value":"2F17","name":"KANGXI RADICAL TEN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5341","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F17"},12056:{"value":"2F18","name":"KANGXI RADICAL DIVINATION","category":"So","class":"0","bidirectional_category":"ON","mapping":" 535C","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F18"},12057:{"value":"2F19","name":"KANGXI RADICAL SEAL","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5369","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F19"},12058:{"value":"2F1A","name":"KANGXI RADICAL CLIFF","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5382","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F1A"},12059:{"value":"2F1B","name":"KANGXI RADICAL PRIVATE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 53B6","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F1B"},12060:{"value":"2F1C","name":"KANGXI RADICAL AGAIN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 53C8","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F1C"},12061:{"value":"2F1D","name":"KANGXI RADICAL MOUTH","category":"So","class":"0","bidirectional_category":"ON","mapping":" 53E3","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F1D"},12062:{"value":"2F1E","name":"KANGXI RADICAL ENCLOSURE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 56D7","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F1E"},12063:{"value":"2F1F","name":"KANGXI RADICAL EARTH","category":"So","class":"0","bidirectional_category":"ON","mapping":" 571F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F1F"},12064:{"value":"2F20","name":"KANGXI RADICAL SCHOLAR","category":"So","class":"0","bidirectional_category":"ON","mapping":" 58EB","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F20"},12065:{"value":"2F21","name":"KANGXI RADICAL GO","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5902","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F21"},12066:{"value":"2F22","name":"KANGXI RADICAL GO SLOWLY","category":"So","class":"0","bidirectional_category":"ON","mapping":" 590A","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F22"},12067:{"value":"2F23","name":"KANGXI RADICAL EVENING","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5915","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F23"},12068:{"value":"2F24","name":"KANGXI RADICAL BIG","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5927","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F24"},12069:{"value":"2F25","name":"KANGXI RADICAL WOMAN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5973","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F25"},12070:{"value":"2F26","name":"KANGXI RADICAL CHILD","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5B50","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F26"},12071:{"value":"2F27","name":"KANGXI RADICAL ROOF","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5B80","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F27"},12072:{"value":"2F28","name":"KANGXI RADICAL INCH","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5BF8","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F28"},12073:{"value":"2F29","name":"KANGXI RADICAL SMALL","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5C0F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F29"},12074:{"value":"2F2A","name":"KANGXI RADICAL LAME","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5C22","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F2A"},12075:{"value":"2F2B","name":"KANGXI RADICAL CORPSE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5C38","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F2B"},12076:{"value":"2F2C","name":"KANGXI RADICAL SPROUT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5C6E","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F2C"},12077:{"value":"2F2D","name":"KANGXI RADICAL MOUNTAIN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5C71","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F2D"},12078:{"value":"2F2E","name":"KANGXI RADICAL RIVER","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5DDB","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F2E"},12079:{"value":"2F2F","name":"KANGXI RADICAL WORK","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5DE5","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F2F"},12080:{"value":"2F30","name":"KANGXI RADICAL ONESELF","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5DF1","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F30"},12081:{"value":"2F31","name":"KANGXI RADICAL TURBAN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5DFE","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F31"},12082:{"value":"2F32","name":"KANGXI RADICAL DRY","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5E72","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F32"},12083:{"value":"2F33","name":"KANGXI RADICAL SHORT THREAD","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5E7A","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F33"},12084:{"value":"2F34","name":"KANGXI RADICAL DOTTED CLIFF","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5E7F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F34"},12085:{"value":"2F35","name":"KANGXI RADICAL LONG STRIDE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5EF4","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F35"},12086:{"value":"2F36","name":"KANGXI RADICAL TWO HANDS","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5EFE","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F36"},12087:{"value":"2F37","name":"KANGXI RADICAL SHOOT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5F0B","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F37"},12088:{"value":"2F38","name":"KANGXI RADICAL BOW","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5F13","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F38"},12089:{"value":"2F39","name":"KANGXI RADICAL SNOUT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5F50","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F39"},12090:{"value":"2F3A","name":"KANGXI RADICAL BRISTLE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5F61","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F3A"},12091:{"value":"2F3B","name":"KANGXI RADICAL STEP","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5F73","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F3B"},12092:{"value":"2F3C","name":"KANGXI RADICAL HEART","category":"So","class":"0","bidirectional_category":"ON","mapping":" 5FC3","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F3C"},12093:{"value":"2F3D","name":"KANGXI RADICAL HALBERD","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6208","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F3D"},12094:{"value":"2F3E","name":"KANGXI RADICAL DOOR","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6236","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F3E"},12095:{"value":"2F3F","name":"KANGXI RADICAL HAND","category":"So","class":"0","bidirectional_category":"ON","mapping":" 624B","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F3F"},12096:{"value":"2F40","name":"KANGXI RADICAL BRANCH","category":"So","class":"0","bidirectional_category":"ON","mapping":" 652F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F40"},12097:{"value":"2F41","name":"KANGXI RADICAL RAP","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6534","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F41"},12098:{"value":"2F42","name":"KANGXI RADICAL SCRIPT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6587","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F42"},12099:{"value":"2F43","name":"KANGXI RADICAL DIPPER","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6597","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F43"},12100:{"value":"2F44","name":"KANGXI RADICAL AXE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 65A4","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F44"},12101:{"value":"2F45","name":"KANGXI RADICAL SQUARE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 65B9","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F45"},12102:{"value":"2F46","name":"KANGXI RADICAL NOT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 65E0","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F46"},12103:{"value":"2F47","name":"KANGXI RADICAL SUN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 65E5","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F47"},12104:{"value":"2F48","name":"KANGXI RADICAL SAY","category":"So","class":"0","bidirectional_category":"ON","mapping":" 66F0","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F48"},12105:{"value":"2F49","name":"KANGXI RADICAL MOON","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6708","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F49"},12106:{"value":"2F4A","name":"KANGXI RADICAL TREE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6728","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F4A"},12107:{"value":"2F4B","name":"KANGXI RADICAL LACK","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6B20","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F4B"},12108:{"value":"2F4C","name":"KANGXI RADICAL STOP","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6B62","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F4C"},12109:{"value":"2F4D","name":"KANGXI RADICAL DEATH","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6B79","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F4D"},12110:{"value":"2F4E","name":"KANGXI RADICAL WEAPON","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6BB3","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F4E"},12111:{"value":"2F4F","name":"KANGXI RADICAL DO NOT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6BCB","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F4F"},12112:{"value":"2F50","name":"KANGXI RADICAL COMPARE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6BD4","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F50"},12113:{"value":"2F51","name":"KANGXI RADICAL FUR","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6BDB","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F51"},12114:{"value":"2F52","name":"KANGXI RADICAL CLAN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6C0F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F52"},12115:{"value":"2F53","name":"KANGXI RADICAL STEAM","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6C14","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F53"},12116:{"value":"2F54","name":"KANGXI RADICAL WATER","category":"So","class":"0","bidirectional_category":"ON","mapping":" 6C34","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F54"},12117:{"value":"2F55","name":"KANGXI RADICAL FIRE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 706B","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F55"},12118:{"value":"2F56","name":"KANGXI RADICAL CLAW","category":"So","class":"0","bidirectional_category":"ON","mapping":" 722A","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F56"},12119:{"value":"2F57","name":"KANGXI RADICAL FATHER","category":"So","class":"0","bidirectional_category":"ON","mapping":" 7236","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F57"},12120:{"value":"2F58","name":"KANGXI RADICAL DOUBLE X","category":"So","class":"0","bidirectional_category":"ON","mapping":" 723B","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F58"},12121:{"value":"2F59","name":"KANGXI RADICAL HALF TREE TRUNK","category":"So","class":"0","bidirectional_category":"ON","mapping":" 723F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F59"},12122:{"value":"2F5A","name":"KANGXI RADICAL SLICE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 7247","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F5A"},12123:{"value":"2F5B","name":"KANGXI RADICAL FANG","category":"So","class":"0","bidirectional_category":"ON","mapping":" 7259","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F5B"},12124:{"value":"2F5C","name":"KANGXI RADICAL COW","category":"So","class":"0","bidirectional_category":"ON","mapping":" 725B","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F5C"},12125:{"value":"2F5D","name":"KANGXI RADICAL DOG","category":"So","class":"0","bidirectional_category":"ON","mapping":" 72AC","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F5D"},12126:{"value":"2F5E","name":"KANGXI RADICAL PROFOUND","category":"So","class":"0","bidirectional_category":"ON","mapping":" 7384","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F5E"},12127:{"value":"2F5F","name":"KANGXI RADICAL JADE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 7389","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F5F"},12128:{"value":"2F60","name":"KANGXI RADICAL MELON","category":"So","class":"0","bidirectional_category":"ON","mapping":" 74DC","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F60"},12129:{"value":"2F61","name":"KANGXI RADICAL TILE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 74E6","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F61"},12130:{"value":"2F62","name":"KANGXI RADICAL SWEET","category":"So","class":"0","bidirectional_category":"ON","mapping":" 7518","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F62"},12131:{"value":"2F63","name":"KANGXI RADICAL LIFE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 751F","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F63"},12132:{"value":"2F64","name":"KANGXI RADICAL USE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 7528","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F64"},12133:{"value":"2F65","name":"KANGXI RADICAL FIELD","category":"So","class":"0","bidirectional_category":"ON","mapping":" 7530","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F65"},12134:{"value":"2F66","name":"KANGXI RADICAL BOLT OF CLOTH","category":"So","class":"0","bidirectional_category":"ON","mapping":" 758B","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F66"},12135:{"value":"2F67","name":"KANGXI RADICAL SICKNESS","category":"So","class":"0","bidirectional_category":"ON","mapping":" 7592","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F67"},12136:{"value":"2F68","name":"KANGXI RADICAL DOTTED TENT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 7676","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F68"},12137:{"value":"2F69","name":"KANGXI RADICAL WHITE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 767D","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F69"},12138:{"value":"2F6A","name":"KANGXI RADICAL SKIN","category":"So","class":"0","bidirectional_category":"ON","mapping":" 76AE","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F6A"},12139:{"value":"2F6B","name":"KANGXI RADICAL DISH","category":"So","class":"0","bidirectional_category":"ON","mapping":" 76BF","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F6B"},12140:{"value":"2F6C","name":"KANGXI RADICAL EYE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 76EE","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F6C"},12141:{"value":"2F6D","name":"KANGXI RADICAL SPEAR","category":"So","class":"0","bidirectional_category":"ON","mapping":" 77DB","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F6D"},12142:{"value":"2F6E","name":"KANGXI RADICAL ARROW","category":"So","class":"0","bidirectional_category":"ON","mapping":" 77E2","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F6E"},12143:{"value":"2F6F","name":"KANGXI RADICAL STONE","category":"So","class":"0","bidirectional_category":"ON","mapping":" 77F3","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F6F"},12144:{"value":"2F70","name":"KANGXI RADICAL SPIRIT","category":"So","class":"0","bidirectional_category":"ON","mapping":" 793A","decimal_digit_value":"","digit_value":"","numeric_value":"","mirrored":"N","unicode_name":"","comment":"","uppercase_mapping":"","lowercase_mapping":"","titlecase_mapping":"","symbol":"\u2F70"},12145:{"value":"2F71","name":"KANGXI RADICAL TRACK","category":"So","class":"0","bidirectional_category":"ON","mapping":"